ExpandableListView 二级列表实现过程

  • 相关属性
  • 实现步骤
  • BaseExpandableListAdpter
  • 代码片段


相关属性

  • android:childDivider:指定各组内子类表项之间的分隔条,图片不会完全显示, 分离子列表项的是一条直线
  • android:childIndicator:显示在子列表旁边的Drawable对象,可以是一个图像
  • android:groupIndicator:显示在组列表旁边的Drawable对象,可以是一个图像
  • android:childIndicatorEnd:子列表项指示符的结束约束位置
  • android:childIndicatorLeft:子列表项指示符的左边约束位置
  • android:childIndicatorRight:子列表项指示符的右边约束位置
  • android:childIndicatorStart:子列表项指示符的开始约束位置
  • android:indicatorEnd:组列表项指示器的结束约束位置
  • android:indicatorLeft:组列表项指示器的左边约束位置
  • android:indicatorRight:组列表项指示器的右边约束位置
  • android:indicatorStart:组列表项指示器的开始约束位置

实现步骤

  1. 扩展BaseExpandableListAdpter实现ExpandableAdapter。
  2. 使用SimpleExpandableListAdpater将两个List集合包装成ExpandableAdapter
  3. 使用simpleCursorTreeAdapter将Cursor中的数据包装成SimpleCuroTreeAdapter

本节示例使用的是第一个,扩展BaseExpandableListAdpter,我们需要重写该类中的相关方法, 下面我们通过一个代码示例来体验下!

  1. 定义 Layout 样式
    先制定Group组的样式 Layout (item_exlist_group.xml)
    再制定 每个组 下面项 的 样式(item_exlist_item.xml)
  2. 设置 数据适配器
    先设置 Group 类 和 Item 类 存放数据
    然后自定义数据适配器 实现抽象类 BaseExpandableListAdapter (MyBaseExpandableListAdapter.java)
  3. 设置布局文件:activity_main.xml
  4. 最后 MainActivity.java 代码

BaseExpandableListAdpter

代码片段

item_exlist_group.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="5dp"
    >
    <!--
        设置组的样式

        textStyle:
        Android 提供了三个样式
        1 normal 正常字体
        2 bold 粗体
        3 italic 斜体

    -->
    <TextView
        android:id="@+id/tv_group_name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center_vertical"
        android:paddingStart="30dp"
        android:text="@string/group_name"
        android:textStyle="bold"
        android:textSize="25sp" />

</LinearLayout>

item_exlist_item.xml

<?xml version="1.0" encoding="utf-8"?>
<!--设置 组 里面的项 内容排布-->
<?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="3dp"
    android:background="@color/ItemColor"
    >
    <ImageView
        android:id="@+id/image_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/ic_baseline_camera_24"
        />

    <TextView
        android:id="@+id/tv_bookName"

        android:layout_width="230dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:focusable="false"
        android:text="@string/book_name"
        android:textColor="@color/black"
        android:textSize="18sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/tv_bookPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1"
        android:textStyle="bold"
        android:textSize="17sp"
        android:layout_marginTop="18dp"

        />
</LinearLayout>

MyBaseExpandableListAdapter.java
设置适配器

  1. 设置组类
    Group.java
package com.example.expandablelistviewstudy;

/**
 * 设置 组
 */
public class Group {
    private String gName;

    private Group() {
    }

    public Group(String gName) {
        this.gName = gName;
    }

    public String getGName() {
        return gName;
    }

    public void setGName(String gName) {
        this.gName = gName;
    }
}
  1. 设置子项类
    Item.java
package com.example.expandablelistviewstudy;

import android.widget.ImageView;

import java.math.BigDecimal;

/**
 * 设置 组下面的子项 里的内容
 */
public class Item {

    private int iId;
    private String iName;
    private BigDecimal bookPrice;

    public Item(int iId, String iName,BigDecimal bookPrice) {
        this.iId = iId;
        this.iName = iName;
        this.bookPrice = bookPrice;
    }


    public BigDecimal getBookPrice() {
        return bookPrice;
    }

    public void setBookPrice(BigDecimal bookPrice) {
        this.bookPrice = bookPrice;
    }

    public int getIId() {
        return iId;
    }

    public String getIName() {
        return iName;
    }

    public void setIId(int iId) {
        this.iId = iId;
    }

    public void setIName(String iName) {
        this.iName = iName;
    }
}

设置数据适配器
MyBaseExpandableListAdapter.java

package com.example.expandablelistviewstudy;

import android.content.Context;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.util.ArrayList;

/**
 * MyBaseExpandableListAdapter.java
 * 设置 数据适配器
 * 自定义数据适配器 实现抽象类 BaseExpandableListAdapter
 */
public class MyBaseExpandableListAdapter extends BaseExpandableListAdapter {
    //组
    private ArrayList<Group> gGroups ;
    //子项
    private ArrayList<ArrayList<Item>> iItems;
    //上下文
    private Context mContext;

    //构造器
    public MyBaseExpandableListAdapter(Context mContext, ArrayList<Group> gGroups, ArrayList<ArrayList<Item>> iItems ){

        this.mContext = mContext;
        this.gGroups = gGroups;
        this.iItems = iItems;

    }
    @Override
    public int getGroupCount() {
        //获取所有分组个数
        return this.gGroups.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        //获取 指定 (groupPosition)分组的  子项 个数
        //因为 iItems 是由一个ArrayList<ArrayList<Item>> 就相当于  二维数组  [] []
        //[0] [0]
        //[1] [1]
        //所以就一一对应 当我们需要找 第一个组里面的 子项的时候
        //第一个组 下标就是  0   然后 我们就可以获取iItem 在 0,0 位置的一共由多少个个数
        return iItems.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        //获取指定(groupPosition) 组 对象

        return gGroups.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        //获取指定(groupPosition)分组的 (childPosition)子项 对象

        return iItems.get(groupPosition).get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        //获取 指定 组 Id
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        //获取 指定 (groupPosition)组的指定 (childPosition)子项 Id
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        //如果返回true,表示子项和组的ID始终表示一个固定的组件对象
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        //获取指定(groupPosition)组的 view 组件
        ViewHolderGroup groupHolder ;

        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_exlist_group, parent, false);
            groupHolder = new ViewHolderGroup();
            groupHolder.tv_group_name = (TextView) convertView.findViewById(R.id.tv_group_name);
            convertView.setTag(groupHolder);
        }else{
            groupHolder = (ViewHolderGroup) convertView.getTag();
        }
        groupHolder.tv_group_name.setText(gGroups.get(groupPosition).getGName());

        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        //获得指定(groupPosition)组中的(childPosition)子项的 view 组件
        ViewHolderItem itemHolder;
        if(convertView == null){
            convertView = LayoutInflater.from(mContext).inflate(
                    R.layout.item_exlist_item,parent,false);
            itemHolder = new ViewHolderItem();
            itemHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_bookName);
            itemHolder.img_icon = (ImageView) convertView.findViewById(R.id.image_icon);
            itemHolder.tv_bookPrice =(TextView) convertView.findViewById(R.id.tv_bookPrice);
            convertView.setTag(itemHolder);

        }else{

            itemHolder = (ViewHolderItem) convertView.getTag();
        }
        itemHolder.img_icon.setImageResource(iItems.get(groupPosition).get(childPosition).getIId());
        itemHolder.tv_name.setText(iItems.get(groupPosition).get(childPosition).getIName());
        itemHolder.tv_bookPrice.setText(iItems.get(groupPosition).get(childPosition).getBookPrice() + "元");

        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        //项是否可以被选中
        return true;
    }

    private static class ViewHolderGroup{
        private TextView tv_group_name;
    }

    private static class ViewHolderItem{
        private ImageView img_icon;
        private TextView tv_name;
        private TextView tv_bookPrice;

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ExpandableListView
        android:id="@+id/exList_books"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:childDivider="#F1E7E7"

        />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.example.expandablelistviewstudy;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Toast;

import java.math.BigDecimal;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private ArrayList<Group> groups = null;
    private  ArrayList<ArrayList<Item>> iItems = null;

    private ArrayList<Item> item = null;
    private Context mContext;
    private ExpandableListView exList_books;
    private MyBaseExpandableListAdapter myAdapter = null;

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

        mContext = MainActivity.this;
        exList_books = findViewById(R.id.exList_books);
        /**
         * 书本分组
         */
        groups = new ArrayList<>();
        groups.add(new Group("文学"));
        groups.add(new Group("哲学"));
        groups.add(new Group("其它"));

        /**
         * 书本分组的子项
         */
        iItems = new ArrayList<>();
        item = new ArrayList<>();

        //文学
        item.add(new Item(R.drawable.snipaste_eegnhya, "额尔古纳河右岸",new BigDecimal("19.00")));
        iItems.add(item);

        //哲学
        item = new ArrayList<>();
        item.add(new Item(R.drawable.snipaste_ttlvt, "天堂旅行团",new BigDecimal("30.00")));
        iItems.add(item);

        //其它
        item = new ArrayList<>();
        item.add(new Item(R.drawable.snipaste_ybygxmb, "云边有个小卖部",new BigDecimal("40.00")));
        iItems.add(item);

        myAdapter = new MyBaseExpandableListAdapter(mContext,groups,iItems);
        exList_books.setAdapter(myAdapter);


        exList_books.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(mContext, "你点击了:" + iItems.get(groupPosition).get(childPosition).getIName(), Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }
}

android二级列表样式 安卓二级列表_android二级列表样式