Android笔记——ExpandableListV的使用和三级list的实现

写这篇的原因说起来很惭愧,面试的时候被问怎么实现二级list,我没接触过expandablelistview支支吾吾的回答用listview扩展getcount(),面试官说expandablelistview很基础的东西你都没用过,接着便是一些我也回答不上了的问题。。。

回归正题,ExpandableListView是用于实现二级listview的控件,其用法几乎和listview一样,在xml中添加,代码中获取id,实现适配器,设置适配器。不同的是,使用自定义ExpandableListView时所需设置的适配器的一些方法需要重写。这里以实现3级list作为一个例子。

首先是数据的准备,这里简单准备一下数据

<pre style="background-color:#1e1e1a;color:#a9b7c6;font-family:'Consolas';font-size:9.0pt;"><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">>>> </span><span style="color:#58c5e7;">dataMap </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">HashMap</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f4005d;">String</span><span style="color:#efefe8;">[] </span><span style="color:#58c5e7;">str1 </span><span style="color:#fd9720;">= </span><span style="color:#f6f6ef;">{</span><span style="color:#e0d067;">"first"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"second"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"third"</span><span style="color:#f6f6ef;">}</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f4005d;">String</span><span style="color:#efefe8;">[] </span><span style="color:#58c5e7;">str2 </span><span style="color:#fd9720;">= </span><span style="color:#f6f6ef;">{</span><span style="color:#e0d067;">"1"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"2"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"3"</span><span style="color:#ea882f;">, </span><span style="color:#e0d067;">"4"</span><span style="color:#f6f6ef;">}</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">Map</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#ea882f;">, </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">>> </span><span style="color:#58c5e7;">childMap </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">HashMap</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;
</span><span style="color:#fd9720;">private </span><span style="color:#f63ce6;">List</span><span style="color:#fd9720;"><</span><span style="color:#f4005d;">String</span><span style="color:#fd9720;">> </span><span style="color:#58c5e7;">childList </span><span style="color:#fd9720;">= new </span><span style="color:#b4dc27;">ArrayList</span><span style="color:#fd9720;"><></span><span style="color:#efefe8;">()</span><span style="color:#fd9720;">;</span>
Map嵌套,简单的放一下数据,然后是初始化数据

private void initData(){
    childList.add("f1");
    childList.add("f2");
    childList.add("f3");
    childMap.put(str2[0], childList);
    childMap.put(str2[1], childList);
    childMap.put(str2[2], childList);
    childMap.put(str2[3], childList);
    dataMap.put(str1[0], childMap);
    dataMap.put(str1[1], childMap);
    dataMap.put(str1[2], childMap);
}

最重要的来了,我们需要为自己的ExpandableListView写适配器,继承自BaseExpandableListAdapter
private class GroupExpandableListViewAdapter extends BaseExpandableListAdapter{


    @Override
    public Object getGroup(int parentPos){
        return dataMap.get(str1[parentPos]);
    }
    @Override
    public Object getChild(int parentPos, int childPos){
        return dataMap.get(str1[parentPos]).get(childPos);
    }

    @Override
    public int getGroupCount(){
        return dataMap.size();
    }

    @Override
    public int getChildrenCount(int parentPos){
        return 1;
    }

    @Override
    public long getGroupId(int parentPos){
        return parentPos;
    }

    @Override
    public long getChildId(int parentPos, int childPos){
        return  childPos;
    }

    @Override
    public boolean hasStableIds(){
        return false;
    }

    @Override
    public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
        if(view == null){
            LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.group_item, null);
        }
        view.setTag(R.layout.group_item, parentPos);
        view.setTag(R.layout.child_item, -1);
        TextView groupText = (TextView) view.findViewById(R.id.group_item);
        groupText.setText(str1[parentPos]);
        return view;

    }

    @Override
    public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
        if(view == null){
            LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.child_listview, null);
        }
        view.setTag(R.layout.group_item, parentPos);
        view.setTag(R.layout.child_item, childPos);

        ChildExpandableListView childExpandableListView = (ChildExpandableListView) view.findViewById(R.id.child_listview);
        ChildExpandableListViewAdapter childExpandableLVAdapter = new ChildExpandableListViewAdapter();
        childExpandableListView.setAdapter(childExpandableLVAdapter);
        return view;
    }

    @Override
    public boolean isChildSelectable(int i, int i1){
        return true;
    }

}
这里解释一下,最重要的两个:getGroupView是获取list中父级内容的,第一层的父级很简单,只有一个TextView;
getChildView是获取list中子项内容的。想一下,由于要实现3级的list,第一季的list子项自然也是ExpandableListView,而且每一个父项里只有一个ExpandableListView。
在getChildView中获取到第二级的ExpandableListView,并且实现它的适配器(注意第一级和第二级的适配器类型是不一样的),并设置好适配器
需要注意的是,第一级中isChildSelectable的返回值一定要设为true,该方法是用于判断子项能否被点击的,我们实现3级菜单,所以必然要设为true。
所以这里getChildCount返回的子项个数是1,我们只需要一个ExpandableListView来表示子项内容,子项里具体的东西再交给下一级的getGroupView来实现。
这里我用了自定义的ChildExpandableListView,之所以自定义是因为,双层的ExpandableListView嵌套会使第一层子项的内容显示不全,百度后得知需要重绘他的高度,这里是ChildExpandableListView的代码:
public class ChildExpandableListView extends ExpandableListView {

    public ChildExpandableListView(Context context) {
        super(context);
    }

    public ChildExpandableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ChildExpandableListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

最后是第二级ExpandableListView,很简单,是普通的ExpandableListView的用法,父项只有一个TExtView,子项也只有一个TextView。
private class ChildExpandableListViewAdapter extends BaseExpandableListAdapter{


    @Override
    public Object getGroup(int parentPos){
        return childMap.get(str2[parentPos]);
    }
    @Override
    public Object getChild(int parentPos, int childPos){
        return childMap.get(str2[parentPos]).get(childPos);
    }

    @Override
    public int getGroupCount(){
        return childMap.size();
    }

    @Override
    public int getChildrenCount(int parentPos){
        return childMap.get(str2[parentPos]).size();
    }

    @Override
    public long getGroupId(int parentPos){
        return parentPos;
    }

    @Override
    public long getChildId(int parentPos, int childPos){
        return  childPos;
    }

    @Override
    public boolean hasStableIds(){
        return false;
    }

    @Override
    public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
        if(view == null){
            LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.child_item, null);
        }
        view.setTag(R.layout.group_item, parentPos);
        view.setTag(R.layout.child_item, -1);
        TextView childText = (TextView) view.findViewById(R.id.child_item);
        childText.setText(str2[parentPos]);
        return view;

    }

    @Override
    public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
        if(view == null){
            LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.child_child_item, null);
        }
        view.setTag(R.layout.group_item, parentPos);
        view.setTag(R.layout.child_item, childPos);

        TextView child_child_text = (TextView) view.findViewById(R.id.child_child_item);
        child_child_text.setText(childMap.get(str2[parentPos]).get(childPos));
        return view;
    }

    @Override
    public boolean isChildSelectable(int i, int i1){
        return true;
    }

}
第二级中只需要加载父项和子项的内容即可。
最后实现效果:



以下是全部代码:
package com.example.yxc.expandlistviewtest;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private ExpandableListView expandableListView;
    private Map<String, Map<String, List<String>>> dataMap = new HashMap<>();
    private String[] str1 = {"first", "second", "third"};
    private String[] str2 = {"1", "2", "3", "4"};
    private Map<String, List<String>> childMap = new HashMap<>();
    private List<String> childList = new ArrayList<>();
    private GroupExpandableListViewAdapter mExpandableListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initData();

        expandableListView = (ExpandableListView) findViewById(R.id.listview);
        mExpandableListAdapter = new GroupExpandableListViewAdapter();
        expandableListView.setAdapter(mExpandableListAdapter);

        expandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView expandableListView, View view, int parentPos, int childPos, long l) {
                Toast.makeText(MainActivity.this,
                        "you press the childitem " + childMap.get(str2[parentPos]).get(childPos),
                        Toast.LENGTH_SHORT).show();
                return false;
            }
        });
    }

    private void initData(){
        childList.add("f1");
        childList.add("f2");
        childList.add("f3");
        childMap.put(str2[0], childList);
        childMap.put(str2[1], childList);
        childMap.put(str2[2], childList);
        childMap.put(str2[3], childList);
        dataMap.put(str1[0], childMap);
        dataMap.put(str1[1], childMap);
        dataMap.put(str1[2], childMap);
    }

    private class GroupExpandableListViewAdapter extends BaseExpandableListAdapter{


        @Override
        public Object getGroup(int parentPos){
            return dataMap.get(str1[parentPos]);
        }
        @Override
        public Object getChild(int parentPos, int childPos){
            return dataMap.get(str1[parentPos]).get(childPos);
        }

        @Override
        public int getGroupCount(){
            return dataMap.size();
        }

        @Override
        public int getChildrenCount(int parentPos){
            return 1;
        }

        @Override
        public long getGroupId(int parentPos){
            return parentPos;
        }

        @Override
        public long getChildId(int parentPos, int childPos){
            return  childPos;
        }

        @Override
        public boolean hasStableIds(){
            return false;
        }

        @Override
        public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
            if(view == null){
                LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.group_item, null);
            }
            view.setTag(R.layout.group_item, parentPos);
            view.setTag(R.layout.child_item, -1);
            TextView groupText = (TextView) view.findViewById(R.id.group_item);
            groupText.setText(str1[parentPos]);
            return view;

        }

        @Override
        public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
            if(view == null){
                LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.child_listview, null);
            }
            view.setTag(R.layout.group_item, parentPos);
            view.setTag(R.layout.child_item, childPos);

            ChildExpandableListView childExpandableListView = (ChildExpandableListView) view.findViewById(R.id.child_listview);
            ChildExpandableListViewAdapter childExpandableLVAdapter = new ChildExpandableListViewAdapter();
            childExpandableListView.setAdapter(childExpandableLVAdapter);
            return view;
        }

        @Override
        public boolean isChildSelectable(int i, int i1){
            return true;
        }

    }


    private class ChildExpandableListViewAdapter extends BaseExpandableListAdapter{


        @Override
        public Object getGroup(int parentPos){
            return childMap.get(str2[parentPos]);
        }
        @Override
        public Object getChild(int parentPos, int childPos){
            return childMap.get(str2[parentPos]).get(childPos);
        }

        @Override
        public int getGroupCount(){
            return childMap.size();
        }

        @Override
        public int getChildrenCount(int parentPos){
            return childMap.get(str2[parentPos]).size();
        }

        @Override
        public long getGroupId(int parentPos){
            return parentPos;
        }

        @Override
        public long getChildId(int parentPos, int childPos){
            return  childPos;
        }

        @Override
        public boolean hasStableIds(){
            return false;
        }

        @Override
        public View getGroupView(int parentPos, boolean b, View view, ViewGroup viewGroup){
            if(view == null){
                LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.child_item, null);
            }
            view.setTag(R.layout.group_item, parentPos);
            view.setTag(R.layout.child_item, -1);
            TextView childText = (TextView) view.findViewById(R.id.child_item);
            childText.setText(str2[parentPos]);
            return view;

        }

        @Override
        public View getChildView(int parentPos, int childPos, boolean b, View view, ViewGroup viewGroup){
            if(view == null){
                LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.child_child_item, null);
            }
            view.setTag(R.layout.group_item, parentPos);
            view.setTag(R.layout.child_item, childPos);

            TextView child_child_text = (TextView) view.findViewById(R.id.child_child_item);
            child_child_text.setText(childMap.get(str2[parentPos]).get(childPos));
            return view;
        }

        @Override
        public boolean isChildSelectable(int i, int i1){
            return true;
        }

    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值