ExpandableListView + 自定义ExpandableListAdapter实现复杂列表

       ExpandableListView是ListView的子类,它扩展了ListView,对列表项实现了item分组,它的列表项由ExpandableListAdapter提供。ExpandableListAdapter是一个接口,实现该接口的是一个抽象类BaseExpandableListAdapter。

1、目标    通过ExpandableListView和自定义的ExpandableListAdapter实现主流APP上复杂功能的列表。

2、最终实现效果图

3、实现

     3.1、布局.xml   主布局只需要一个<ExpandableListView>视图即可。

     3.2、实现自定义ExpandableListAdapter   需要继承BaseExpandableListAdapter并实现所有的抽象方法。

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) {
        TextView tv;
        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;
    TextView tv;
    public ViewHolder(ImageView imv, TextView tv) {
        this.imv = imv;
        this.tv = tv;
    }
}

相关重写方法功能介绍:

public int getGroupCount():返回分组item个数

public int getChildrenCount(int groupPosition):返回特定分组中子item的个数

public Object getGroup(int groupPosition):返回特定分组item

public Object getChild(int groupPosition, int childPosition): 返回特定分组中特定位置的子item

itempublic long getGroupId(int groupPosition): 返回分组item的ID

public long getChildId(int groupPosition, int childPosition):返回特定分组中特定位置的子item ID

public boolean hasStableIds():表示分组和子选项是否持有稳定的id。返回false,通过getxxxId来判断哪些需要getxxxView从而达到局部刷新的效果,在getxxxView比较耗时的情况下起到优化的效果。

public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent):是一个最重要方法。获得父列表项视图。convertView参数:Android中的常用Adapter都会涉及到convertView的使用,使用convertView主要是为了缓存视图View,用以增加ListView的item View加载效率。在Adapter的getxxxView中,先判断convertView是否为空null,如果非空,则直接对convertView复用,否则才创建新的View。ViewHolder类是视图组件的持有者,把布局中相关的组件都封装起来,以便使用。setTag()getTag()是把ViewHolder对象和布局关联起来,可以理解为为ViewHolder对象打了一个标签,使它属于相应的布局。因为不同布局使用的ViewHolder可能不同。

public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent):参照上面,返回子item的视图。

public boolean isChildSelectable(int groupPosition, int childPosition):子item是否可点击。

     3.3、封装数据类

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[]{"收藏书架", "时尚服装", "美味小吃", "热映电影"};
    public String[][] items = new String[][] {
            new String[]{"狭义相对论", "时间简史", "鲁滨逊漂流记", "安徒生童话", "琼美卡随想录"},
            new String[]{"羊毛衫", "复古牛仔", "真丝旗袍", "中长款羊毛大衣"},
            new String[]{"驴肉火烧", "真香烤鸭", "三只松鼠", "梭哈辣条", "薯片", "娃哈哈饮品"},
            new String[]{"封神榜", "前任3", "流浪地球", "悬崖之上", "复仇者联盟", "金刚大战哥斯拉"}
    };
    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);

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值