ExpandableListView is a subclass of ListView. It extends ListView and implements item grouping of list items. Its list items are provided by ExpandableListAdapter. ExpandableListAdapter is an interface, and the implementation of this interface is an abstract class BaseExpandableListAdapter.
1. Goal Realize a list of complex functions on mainstream APPs through ExpandableListView and customized ExpandableListAdapter.
2. Final renderings
3. Implementation
3.1. Layout.xml The main layout only requires one
3.2, To implement a custom ExpandableListAdapter you need to inherit BaseExpandableListAdapter and implement all abstract methods.
public class MyExpandableListAdapter extends BaseExpandableListAdapter { private Context context; private List<Item> mData; public MyExpandableListAdapter(Context context, List<Item> mData){ this.context = context; this.mData = mData; } @Override public int getGroupCount() { return mData.size(); } @Override public int getChildrenCount(int groupPosition) { return mData.get(groupPosition).sonText.length; } @Override public Object getGroup(int groupPosition) { return mData.get(groupPosition).groupText; } @Override public Object getChild(int groupPosition, int childPosition) { return mData.get(groupPosition).sonText[childPosition]; } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { LinearLayout ll; ViewHolder vh; if (convertView == null){ ll = new LinearLayout(context); ll.setOrientation(LinearLayout.HORIZONTAL); ImageView imv = new ImageView(context); ViewGroup.LayoutParams lp1 = new ViewGroup.LayoutParams(250, 250); imv.setLayoutParams(lp1); imv.setPadding(100, 0, 0, 0); ll.addView(imv); TextView tv = new TextView(context); tv.setPadding(40, 0, 0, 0); ViewGroup.LayoutParams lp2 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); tv.setLayoutParams(lp2); tv.setGravity(Gravity.CENTER_VERTICAL); tv.setTextSize(20f); ll.addView(tv); vh = new ViewHolder(imv, tv); ll.setTag(vh); } else { ll = (LinearLayout) convertView; vh = (ViewHolder) ll.getTag(); } vh.imv.setImageResource(mData.get(groupPosition).imgId); vh.tv.setText(getGroup(groupPosition).toString()); return ll; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { TextViewtv; if (convertView == null){ tv = new TextView(context); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); tv.setLayoutParams(lp); tv.setGravity(Gravity.CENTER); tv.setTextSize(18f); }else{ tv = (TextView) convertView; } tv.setText(getChild(groupPosition, childPosition).toString()); return tv; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } } class ViewHolder{ ImageView imv; TextViewtv; public ViewHolder(ImageView imv, TextView tv) { this.imv = imv; this.tv = tv; } }
Introduction to related rewriting method functions:
public int getGroupCount(): Returns the number of grouped items
public int getChildrenCount(int groupPosition): Returns the number of child items in a specific group
public Object getGroup(int groupPosition): Returns a specific group item
public Object getChild(int groupPosition, int childPosition): Returns the child item at a specific position in a specific group
itempublic long getGroupId(int groupPosition): Returns the ID of the grouped item
public long getChildId(int groupPosition, int childPosition): Returns the child item ID of a specific position in a specific group
public boolean hasStableIds(): Indicates whether the grouping and sub-options hold stable ids. Return false, and use getxxxId to determine which ones require getxxxView to achieve the effect of partial refresh, which can optimize the effect when getxxxView is time-consuming.
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent): is the most important method. Get the parent list item view. convertView parameter: Commonly used Adapters in Android will involve the use of convertView. The main purpose of using convertView is to cache the view view and increase the loading efficiency of the item view of the ListView. In the getxxxView of the Adapter, first determine whether the convertView is null. If it is not null, directly reuse the convertView, otherwise a new View will be created. The ViewHolder class is the holder of the view component and encapsulates the related components in the layout for easy use. setTag() and getTag() associate the ViewHolder object with the layout, which can be understood as labeling the ViewHolder object so that it belongs to the corresponding layout. Because the ViewHolder used by different layouts may be different.
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent): Refer to the above to return the view of the child item.
public boolean isChildSelectable(int groupPosition, int childPosition): Whether the child item is clickable.
3.3. Encapsulated data class
public class Item { int imgId; String groupText; String[] sonText; public Item(int imgId, String groupText, String[] sonText) { this.imgId = imgId; this.groupText = groupText; this.sonText = sonText; } }
3.4, MainActivity
public class MainActivity extends AppCompatActivity { public int[] imgs = new int[] {R.drawable.book, R.drawable.clothes, R.drawable.foot, R.drawable.movie}; public String[] gt = new String[]{"Collection Bookshelf", "Fashion Clothing", "Delicious Snacks", "Hot Movies"}; public String[][] items = new String[][] { new String[]{"Special Theory of Relativity", "A Brief History of Time", "Robinson Crusoe", "Andersen's Fairy Tales", "Qiongmeka's Random Notes"}, new String[]{"cardigan", "vintage denim", "silk cheongsam", "mid-length wool coat"}, new String[]{"Donkey meat roasted on fire", "Really fragrant roast duck", "Three squirrels", "Stull spicy strips", "Potato chips", "Wahaha drinks"}, new String[]{"Feng Shen Bang", "Predecessor 3", "Wandering Earth", "Above the Cliff", "Avengers", "King Kong vs. Godzilla"} }; private ExpandableListView elv; private MyExpandableListAdapter mela; public List<Item> data = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); elv = findViewById(R.id.elv); for (int i = 0; i < imgs.length; i + + ) { Item it = new Item(imgs[i], gt[i], items[i]); data.add(it); } mela = new MyExpandableListAdapter(this, data); elv.setAdapter(mela); } }