1. 程式人生 > >ExpandableListView,可展開和摺疊的ListView

ExpandableListView,可展開和摺疊的ListView

ExpandableListView介面實現效果:

一、XML程式碼
1.1 activity_expandable_list_view.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ExpandableListView
android:id="@+id/expandableListView" android:layout_width="match_parent" android:layout_height="wrap_content" android:childDivider="#efefef" android:divider="#efefef" android:dividerHeight="1dp" /*去掉分組左邊的箭頭*/ android:groupIndicator="@null"
android:scrollbars="none" />
</RelativeLayout>
1.2 item_group_expandablelistview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
android:orientation="horizontal" android:padding="10dp">
<ImageView android:id="@+id/img_group" android:layout_width="20dp" android:layout_height="20dp" android:scaleType="fitXY" /> <TextView android:id="@+id/tv_group_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:textSize="16sp" /> <TextView android:id="@+id/tv_group_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:textSize="16sp" /> </LinearLayout>
1.3 item_child_expandablelistview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <ImageView
        android:id="@+id/img_child_head"
        android:layout_width="45dp"
        android:layout_height="45dp"
        android:scaleType="fitXY" />

    <TextView
        android:id="@+id/tv_child_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="2dp"
        android:layout_toRightOf="@id/img_child_head"
        android:singleLine="true"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/tv_child_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@id/tv_child_name"
        android:layout_below="@id/tv_child_name"
        android:layout_marginTop="5dp"
        android:singleLine="true"
        android:textSize="14sp" />
</RelativeLayout>

二、Actvity程式碼

public class ExpandableListViewActivity extends Activity {
    private ExpandableListView listView;
    private MyExpandableListViewAdapter adapter;
    private List<GroupData> groupList;
    private List<List<ChildData>> childList;

    private String[] url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expandable_list_view);
        init();
        loadData();
    }

    private void init() {
        listView = (ExpandableListView) findViewById(R.id.expandableListView);
        groupList = new ArrayList<>();
        childList = new ArrayList<>();
        adapter = new MyExpandableListViewAdapter(this, groupList, childList);
        listView.setAdapter(adapter);

        //重寫OnGroupClickListener,實現當展開時,ExpandableListView不自動滾動
        listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                if (parent.isGroupExpanded(groupPosition)) {
                    parent.collapseGroup(groupPosition);
                } else {
                    //第二個引數false表示展開時是否觸發預設滾動動畫
                    parent.expandGroup(groupPosition, false);
                }
                //telling the listView we have handled the group click, and don't want the default actions.
                return true;
            }
        });
    }

    private void loadData() {
        url = new String[]{
                "http://cdn.duitang.com/uploads/item/201506/07/20150607125903_vFWC5.png",
                "http://upload.qqbody.com/ns/20160915/202359954jalrg3mqoei.jpg",
                "http://tupian.qqjay.com/tou3/2016/0726/8529f425cf23fd5afaa376c166b58e29.jpg",
                "http://cdn.duitang.com/uploads/item/201607/13/20160713094718_Xe3Tc.png",
                "http://img3.imgtn.bdimg.com/it/u=1808104956,526590423&fm=11&gp=0.jpg",
                "http://tupian.qqjay.com/tou3/2016/0725/5d6272a4acd7e21b2391aff92f765018.jpg"
        };

        List<String> group = new ArrayList<>();
        group.add("我的裝置");
        group.add("我的好友");
        group.add("初中同學");
        group.add("高中同學");
        group.add("大學同學");

        for (int i = 0; i < group.size(); i++) {
            GroupData gd = new GroupData(group.get(i), (i + 2) + "/" + (2 * i + 2));
            groupList.add(gd);
        }

        for (int i = 0; i < group.size(); i++) {
            List<ChildData> list = new ArrayList<>();
            for (int j = 0; j < 2 * i + 2; j++) {
                ChildData cd = null;
                if (i == 0) {
                    cd = new ChildData("null", "我的手機", "上次登入");
                    list.add(cd);
                    cd = new ChildData("null", "發現新裝置", "玩轉只能信裝置,發現新生活");
                    list.add(cd);
                    break;
                } else {
                    cd = new ChildData(url[j % url.length], "張三" + j, "你好!!!");
                    list.add(cd);
                }
            }
            childList.add(list);
        }
    }
}

三、Adapter程式碼(MyExpandableListViewAdapter)

public class MyExpandableListViewAdapter implements ExpandableListAdapter {
    private Context context;
    private List<GroupData> groupData;
    private List<List<ChildData>> childData;

    public MyExpandableListViewAdapter(Context context, List<GroupData> groupData, List<List<ChildData>> childData) {
        this.context = context;
        this.groupData = groupData;
        this.childData = childData;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {

    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {

    }

    //獲取分組個數
    @Override
    public int getGroupCount() {
        int ret = 0;
        if (groupData != null) {
            ret = groupData.size();
        }
        return ret;
    }

    //獲取groupPosition分組,子列表數量
    @Override
    public int getChildrenCount(int groupPosition) {
        int ret = 0;
        if (childData != null) {
            ret = childData.get(groupPosition).size();
        }
        return ret;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupData.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return childData.get(groupPosition).get(childPosition);
    }

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

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

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

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        GroupViewHolder holder = null;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item_group_expandablelistview, null);
            holder = new GroupViewHolder();
            holder.img = (ImageView) convertView.findViewById(R.id.img_group);
            holder.tv_name = (TextView) convertView.findViewById(R.id.tv_group_name);
            holder.tv_num = (TextView) convertView.findViewById(R.id.tv_group_num);
            convertView.setTag(holder);
        } else {
            holder = (GroupViewHolder) convertView.getTag();
        }
        GroupData groupData = this.groupData.get(groupPosition);
        //是否展開
        if (isExpanded) {
            holder.img.setImageResource(R.drawable.img_bottom);
        } else {
            holder.img.setImageResource(R.drawable.img_right);
        }
        holder.tv_name.setText(groupData.getName());
        holder.tv_num.setText(groupData.getNum());
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        ChildViewHolder holder = null;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item_child_expandablelistview, null);
            holder = new ChildViewHolder();
            holder.img = (ImageView) convertView.findViewById(R.id.img_child_head);
            holder.tv_name = (TextView) convertView.findViewById(R.id.tv_child_name);
            holder.tv_content = (TextView) convertView.findViewById(R.id.tv_child_content);
            convertView.setTag(holder);
        } else {
            holder = (ChildViewHolder) convertView.getTag();
        }
        ChildData childData = this.childData.get(groupPosition).get(childPosition);
        Glide.with(context).load(childData.getUrl()).placeholder(R.mipmap.ic_launcher)
        .error(R.mipmap.ic_launcher).into(holder.img);
        holder.tv_name.setText(childData.getName());
        holder.tv_content.setText(childData.getContent());
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

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

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

    @Override
    public void onGroupExpanded(int groupPosition) {

    }

    @Override
    public void onGroupCollapsed(int groupPosition) {

    }

    @Override
    public long getCombinedChildId(long groupId, long childId) {
        return 0;
    }

    @Override
    public long getCombinedGroupId(long groupId) {
        return 0;
    }

    class GroupViewHolder {
        ImageView img;
        TextView tv_name, tv_num;
    }

    class ChildViewHolder {
        ImageView img;
        TextView tv_name, tv_content;
    }

}

四、實體類程式碼

GroupData:

public class GroupData implements Serializable {
    private String name;
    private String num;

    public GroupData(String name) {
        this.name = name;
    }

    public GroupData(String name, String num) {
        this.name = name;
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }
}

ChildData:

public class ChildData implements Serializable {
    private String url;
    private String name;
    private String content;

    public ChildData(String url, String name, String content) {
        this.url = url;
        this.name = name;
        this.content = content;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

頭像是通過Glide獲取,gradle匯入Glide以及Glide的簡單實用。

compile 'com.github.bumptech.glide:glide:3.7.0'

Glide.with(context).load(childData.getUrl())
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher).into(holder.img);

placeholder:圖片載入到之前顯示的圖片
error:圖片載入失敗顯示的圖片

分組向右、向下的2張圖片:img_right.png img_bottom.png

不足之處,希望各位大神能夠給予批評和指正。