[メモ]ExpandableListAdapterをカスタムする際のメモ。
ListViewまわりのあれこれをメモ2です。ExpandableListAdapterをカスタムする際のメモ。BaseExpandableListAdapterの使い方とか見るとごっちゃりしとるので今回は使いまわししたいBindableAdapterの作り方を元に同じように使えるBaseExpandableListAdapterを作ってみる。BindableAdapterについては以下様をhttps://github.com/JakeWharton/u2020/blob/master/src/main/java/com/jakewharton/u2020/ui/misc/BindableAdapter.javahttp://rejasupotaro.github.io/2014/02/06/34.htmlそれでは。。。BaseExpandableListAdapterですが、ListAdapterのgetViewに相当するものが以下です。//親のViewpublic View getGroupView(int groupPosition, boolean isExpanded, View convertView,ViewGroup parent);//子供のViewpublic View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent);なのでここをBindableAdapterのようにしてやれば終わり。あとはget関係などは継承してもついてないのでgetGroupCountとか自分で設置する必要はあります。ざざっとかいてしまうと以下です。*子データをよくMapにしているサンプルがありますが個人的にリストのほうが管理しやすいのでListにしてます。public abstract class BindableExpandableAdapter<G,C> extends BaseExpandableListAdapter { private LayoutInflater mInflater; private List<G> mGroupData; private List<List<C>> mChildData; public BindableExpandableAdapter(Context context, List<G> laptops, List<List<C>> laptopCollections) { //this.context = context; this.mChildData = laptopCollections; this.mGroupData = laptops; init(context); } private void init(Context context) { mInflater = LayoutInflater.from(context); } public C getChild(int groupPosition, int childPosition) { return mChildData.get(groupPosition).get(childPosition); } public int getChildrenCount(int groupPosition) { return mChildData.get(groupPosition).size(); } public long getChildId(int groupPosition, int childPosition) { return childPosition; } public boolean getLastChild(int groupPosition, int childPosition) { return mChildData.get(groupPosition).size()-1==childPosition?true:false; } public G getGroup(int groupPosition) { return mGroupData.get(groupPosition); } public int getGroupCount() { return mGroupData.size(); } public long getGroupId(int groupPosition) { return groupPosition; } public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } public boolean hasStableIds() { return true; } public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { View v; if (convertView == null) { v = newGroupView(mInflater, groupPosition, parent,isExpanded); if (v == null) { throw new IllegalStateException("newGroupView result must not be null."); } } else { v = convertView; } bindGroupView( mGroupData.get(groupPosition), groupPosition,v,isExpanded); return v; } public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { View v; if (convertView == null) { v = newChildView(mInflater,groupPosition,childPosition,parent,isLastChild); if (v == null) { throw new IllegalStateException("newChildView result must not be null."); } } else { v = convertView; } bindChildView( mChildData.get(groupPosition).get(childPosition),groupPosition,childPosition,v,isLastChild); return v; } public abstract View newGroupView(LayoutInflater inflater, int groupPosition, ViewGroup container,boolean isExpanded); public abstract View newChildView(LayoutInflater inflater, int groupPosition, int childPosition, ViewGroup container, boolean isLastChild); public abstract void bindGroupView( G item, int groupPosition,View view,boolean isExpanded); public abstract void bindChildView(C item,int groupPosition, int childPosition,View view, boolean isLastChild);}あとはこのClassを継承して好きにカスタマイズしたAdapterを作ってExpandableListView.setAdapter(adapter)してあげればOK。*Obj, ChildObjはカスタムオブジェクトです。public class MyExpandableAdapter extends BindableExpandableAdapter<Obj, ChildObj> { public MyExpandableAdapter(Context context, List<Obj> laptops, List<List<ChildObj>> laptopCollections) { super(context, laptops, laptopCollections); } private static class ViewGroupHolder { private TextView label1,label2; private ImageView indicator; ViewGroupHolder(View view) { label1= (TextView) view.findViewById(android.R.id.text1); label2= (TextView) view.findViewById(android.R.id.text2); indicator= (ImageView) view.findViewById(R.id.indicator); } } @Override public View newGroupView(LayoutInflater inflater, int groupPosition, ViewGroup container, boolean isExpanded) { View view = inflater.inflate(R.layout.group_row, container, false); ViewGroupHolder holder = new ViewGroupHolder(view); view.setTag(holder); return view; } @Override public void bindGroupView(Obj item, int groupPosition, View view,boolean isExpanded) { ViewGroupHolder holder = (ViewGroupHolder) view.getTag(); holder.label1.setText(item.name1); holder.label2.setText(item.name2); holder.indicator.setVisibility(View.GONE); if(getChildrenCount(groupPosition)==0){ holder.indicator.setVisibility(View.GONE); }else{ holder.indicator.setImageResource( isExpanded ? R.drawable.expander_open_holo_light : R.drawable.expander_close_holo_light ); holder.indicator.setVisibility(View.VISIBLE); } } private static class ViewChildHolder { private CheckedTextView label; ViewChildHolder(View view) { label = (CheckedTextView) view.findViewById(android.R.id.text1); } } @Override public View newChildView(LayoutInflater inflater, int groupPosition, int childPosition, ViewGroup container, boolean isLastChild) { View view = inflater.inflate(R.layout.child_row, container, false); ViewChildHolder holder = new ViewChildHolder(view); view.setTag(holder); return view; } @Override public void bindChildView(ChildObj item, int groupPosition, int childPosition, View view, boolean isLastChild) { ViewChildHolder holder = (ViewChildHolder) view.getTag(); holder.label.setText(item.name); holder.label.setChecked(item.check); } }OnChildClickListenerとかで返ってきたViewなどを使ってbindGroupView()やbindChildView()を呼べばnotifyDataSetChangedなど使わず、直接Viewを更新できますので便利です。*BindableAdapterでもできます。[メモ]ListViewから個別にViewを取り出すやり方。と組み合わせればListener以外からでも対象のViewが取れるのでいつでも直に更新できる感じになります。特に説明せずコードだけ置いてすいません。こんなところで。今回の話はサンプルファイルでいうとMyArrayAdapter(継承元BindableAdapter)、MyExpandableAdapter(継承元BindableExpandableAdapter)になります。ListViewまわりのあれこれをメモ1,2のサンプルはこちら