安卓 ExpandableListView二级列表使用手册

 ExpandableListView大家都不陌生,只是项目中会不会经常用到那就说不定了,也许你几年都没有使用过一次呢,那不是生疏了,下面来回顾一下ExpandableListView的使用吧:

 

安卓 ExpandableListView二级列表使用手册_第1张图片

那就以QQ为例吧,实现一个类似QQ的二级列表效果:

安卓 ExpandableListView二级列表使用手册_第2张图片

下面来看看怎么实现吧:

1.布局呈上:

直接看其属性:

divider:设置父类之间的分割线样式,具体的设置见childDivider

childDivider:用来设置同一个父项下,子类之间的分割线的样式

如:

android:childDivider="@drawable/child_divider"



    
    

若是要显示圆角的效果:

android:dividerHeight="5dp"

dividerHeight:用于设置分割线的高度

groupIndicator:用于控制父项前面的小箭头用的

若是不想箭头显示那就:

android:groupIndicator="@null"

indicatorLeft:箭头或者自己设置的图片的右边框距离手机左边边缘的距离,类似于marginLeft

indicatorStart:箭头或者自己设置的图片的左边框距离手机左边边缘的距离,类似于marginLeft

indicatorRight和indicatorEnd:箭头或者自己设置的图片的右边框距离手机右边边缘的距离

childIndicator:用于设置子项前显示的图标,不设置的话默认是没有图标的

2.主函数代码:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_simple).setOnClickListener(this);
        findViewById(R.id.btn_normal).setOnClickListener(this);
        findViewById(R.id.btn_indicator).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_normal) {
            startActivity(new Intent(this, NormalExpandActivity.class));
        } else if (id == R.id.btn_indicator) {
            startActivity(new Intent(this, IndicatorExpandActivity.class));
        } else if(id== R.id.btn_simple){
            startActivity(new Intent(this, SimpleExpandActivity.class));
        }
    }

}

3.自定义Indicator的ExpandableListView

/**
 * 自定义 Indicator 的 ExpandableListView
 */
public class IndicatorExpandActivity extends AppCompatActivity {
    private static final String TAG = "IndicatorExpandActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expand);
        final ExpandableListView listView = (ExpandableListView) findViewById(R.id.expandable_list);
        final IndicatorExpandableListAdapter adapter = new IndicatorExpandableListAdapter(Constant.BOOKS, Constant.FIGURES);
        listView.setAdapter(adapter);

        // 清除默认的 Indicator
        listView.setGroupIndicator(null);

        //  设置分组项的点击监听事件
        listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                Log.d(TAG, "onGroupClick: groupPosition:" + groupPosition + ", id:" + id);
                boolean groupExpanded = parent.isGroupExpanded(groupPosition);
                adapter.setIndicatorState(groupPosition, groupExpanded);
                // 请务必返回 false,否则分组不会展开
                return false;
            }
        });

        //  设置子选项点击监听事件
        listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(IndicatorExpandActivity.this, Constant.FIGURES[groupPosition][childPosition], Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }

}

对于处理 Item 的点击事件,常用的有这几类:
*   setOnChildClickListener
*   setOnGroupClickListener
*   setOnGroupCollapseListener
*   setOnGroupExpandListener
它们分别设置单击子选项、单击分组项、分组合并、分组展开的监听器。

4.IndicatorExpandableListAdapter

/**
 *  Indicator 的 ExpandableListView 的适配器
 */
public class IndicatorExpandableListAdapter extends BaseExpandableListAdapter {
    private static final String TAG = "IndicatorExpandableList";
    private String[] groupData;
    private String[][] childData;
    //                用于存放Indicator的集合
    private SparseArray mIndicators;
    private OnGroupExpandedListener mOnGroupExpandedListener;

    public IndicatorExpandableListAdapter(String[] groupData, String[][] childData) {
        this.groupData = groupData;
        this.childData = childData;
        mIndicators = new SparseArray<>();
    }

    public void setOnGroupExpandedListener(OnGroupExpandedListener onGroupExpandedListener) {
        mOnGroupExpandedListener = onGroupExpandedListener;
    }

    //            根据分组的展开闭合状态设置指示器
    public void setIndicatorState(int groupPosition, boolean isExpanded) {
        if (isExpanded) {
            mIndicators.get(groupPosition).setImageResource(R.drawable.ic_expand_less);
        } else {
            mIndicators.get(groupPosition).setImageResource(R.drawable.ic_expand_more);
        }
    }

    @Override
    public int getGroupCount() {
        return groupData.length;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return childData[groupPosition].length;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupData[groupPosition];
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return childData[groupPosition][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 groupViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_group_indicator, parent, false);
            groupViewHolder = new GroupViewHolder();
            groupViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.label_group_indicator);
            groupViewHolder.ivIndicator = (ImageView) convertView.findViewById(R.id.iv_indicator);
            convertView.setTag(groupViewHolder);
        } else {
            groupViewHolder = (GroupViewHolder) convertView.getTag();
        }
        groupViewHolder.tvTitle.setText(groupData[groupPosition]);
        //      把位置和图标添加到Map
        mIndicators.put(groupPosition, groupViewHolder.ivIndicator);
        //      根据分组状态设置Indicator
        setIndicatorState(groupPosition, isExpanded);
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View
            convertView, ViewGroup parent) {
        ChildViewHolder childViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_child, parent, false);
            childViewHolder = new ChildViewHolder();
            childViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.label_expand_child);
            convertView.setTag(childViewHolder);
        } else {
            childViewHolder = (ChildViewHolder) convertView.getTag();
        }
        childViewHolder.tvTitle.setText(childData[groupPosition][childPosition]);
        return convertView;
    }

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

    @Override
    public void onGroupExpanded(int groupPosition) {
        Log.d(TAG, "onGroupExpanded() called with: groupPosition = [" + groupPosition + "]");
        if (mOnGroupExpandedListener != null) {
            mOnGroupExpandedListener.onGroupExpanded(groupPosition);
        }
    }

    @Override
    public void onGroupCollapsed(int groupPosition) {
        Log.d(TAG, "onGroupCollapsed() called with: groupPosition = [" + groupPosition + "]");
    }

    private static class GroupViewHolder {
        TextView tvTitle;
        ImageView ivIndicator;
    }

    private static class ChildViewHolder {
        TextView tvTitle;
    }
}

5.适配器布局:




    

    

6.普通的二级列表形式:

/**
 * 普通 ExpandableListView,支持只展开一个子项
 */
public class NormalExpandActivity extends AppCompatActivity {
    private static final String TAG = "NormalExpandActivity";
    private ExpandableListView mExpandableListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expand);
        mExpandableListView = (ExpandableListView) findViewById(R.id.expandable_list);
        final NormalExpandableListAdapter adapter = new NormalExpandableListAdapter(Constant.BOOKS, Constant.FIGURES);
        mExpandableListView.setAdapter(adapter);
        adapter.setOnGroupExpandedListener(new OnGroupExpandedListener() {
            @Override
            public void onGroupExpanded(int groupPosition) {
                expandOnlyOne(groupPosition);
            }
        });

        //  设置分组项的点击监听事件
        mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                Log.d(TAG, "onGroupClick: groupPosition:" + groupPosition + ", id:" + id);
                // 请务必返回 false,否则分组不会展开
                return false;
            }
        });

        //  设置子选项点击监听事件
        mExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(NormalExpandActivity.this, Constant.FIGURES[groupPosition][childPosition], Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }

    // 每次展开一个分组后,关闭其他的分组
    private boolean expandOnlyOne(int expandedPosition) {
        boolean result = true;
        int groupLength = mExpandableListView.getExpandableListAdapter().getGroupCount();
        for (int i = 0; i < groupLength; i++) {
            if (i != expandedPosition && mExpandableListView.isGroupExpanded(i)) {
                result &= mExpandableListView.collapseGroup(i);
            }
        }
        return result;
    }

}

 适配器:

/**
 * 普通的 ExpandableListView 的适配器
 */
public class NormalExpandableListAdapter extends BaseExpandableListAdapter {
    private static final String TAG = "NormalExpandableListAda";
    private String[] groupData;
    private String[][] childData;
    private OnGroupExpandedListener mOnGroupExpandedListener;

    public NormalExpandableListAdapter(String[] groupData, String[][] childData) {
        this.groupData = groupData;
        this.childData = childData;
    }

    public void setOnGroupExpandedListener(OnGroupExpandedListener onGroupExpandedListener) {
        mOnGroupExpandedListener = onGroupExpandedListener;
    }

    @Override
    public int getGroupCount() {
        return groupData.length;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return childData[groupPosition].length;
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groupData[groupPosition];
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return childData[groupPosition][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 groupViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_group_normal, parent, false);
            groupViewHolder = new GroupViewHolder();
            groupViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.label_group_normal);
            convertView.setTag(groupViewHolder);
        } else {
            groupViewHolder = (GroupViewHolder) convertView.getTag();
        }
        groupViewHolder.tvTitle.setText(groupData[groupPosition]);
        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View
            convertView, ViewGroup parent) {
        ChildViewHolder childViewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_expand_child, parent, false);
            childViewHolder = new ChildViewHolder();
            childViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.label_expand_child);
            convertView.setTag(childViewHolder);
        } else {
            childViewHolder = (ChildViewHolder) convertView.getTag();
        }
        childViewHolder.tvTitle.setText(childData[groupPosition][childPosition]);
        return convertView;
    }

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

    @Override
    public void onGroupExpanded(int groupPosition) {
        Log.d(TAG, "onGroupExpanded() called with: groupPosition = [" + groupPosition + "]");
        if (mOnGroupExpandedListener != null) {
            mOnGroupExpandedListener.onGroupExpanded(groupPosition);
        }
    }

    @Override
    public void onGroupCollapsed(int groupPosition) {
        Log.d(TAG, "onGroupCollapsed() called with: groupPosition = [" + groupPosition + "]");
    }

    private static class GroupViewHolder {
        TextView tvTitle;
    }

    private static class ChildViewHolder {
        TextView tvTitle;
    }
}

 7.使用 SimpleExpandableListAdapter 实现适配器

/**
 * 使用 SimpleExpandableListAdapter 实现适配器
 */
public class SimpleExpandActivity extends AppCompatActivity {
    private static final String TAG = "SimpleExpandActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expand);
        ExpandableListView listView = (ExpandableListView) findViewById(R.id.expandable_list);

        SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(this, initGroupData(),
                R.layout.item_expand_group_normal, new String[]{Constant.BOOK_NAME}, new int[]{R.id.label_group_normal},
                initChildData(), R.layout.item_expand_child, new String[]{Constant.FIGURE_NAME}, new int[]{R.id.label_expand_child});
        listView.setAdapter(adapter);

        //  设置分组项的点击监听事件
        listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                Log.d(TAG, "onGroupClick: groupPosition:" + groupPosition + ", id:" + id);
                // 请务必返回 false,否则分组不会展开
                return false;
            }
        });

        //  设置子选项点击监听事件
        listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
                Toast.makeText(SimpleExpandActivity.this, Constant.FIGURES[groupPosition][childPosition], Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    }

    // 构建分组项显示的数据
    private List> initGroupData() {
        List> list = new ArrayList<>();
        Map map;
        for (int i = 0; i < Constant.BOOKS.length; i++) {
            map = new HashMap<>();
            map.put(Constant.BOOK_NAME, Constant.BOOKS[i]);
            list.add(map);
        }
        return list;
    }

    // 构建子选项显示的数据
    private List>> initChildData() {
        List>> list = new ArrayList<>();
        List> child;
        Map map;
        int row = Constant.FIGURES.length;
        int column = Constant.FIGURES[0].length;
        for (int i = 0; i < row; i++) {
            child = new ArrayList<>();
            for (int j = 0; j < column; j++) {
                map = new HashMap<>();
                map.put(Constant.FIGURE_NAME, Constant.FIGURES[i][j]);
                child.add(map);
            }
            list.add(child);
        }
        return list;
    }

}

8.分组展开监听器:

/**
 *  分组展开监听器
 */
public interface OnGroupExpandedListener {
    /**
     * 分组展开
     *
     * @param groupPosition 分组的位置
     */
    void onGroupExpanded(int groupPosition);
}

9.常量:

/**
 *   常量类
 */
public final class Constant {
    public static final String[] BOOKS = {"我的朋友", "我的闺蜜", "我的女朋友", "我的妹妹"};
    public static final String[][] FIGURES = {
            {"我的朋友有很多所以就不一一介绍了,就算介绍了你也不一定认识!"},
            {"我的闺蜜有很多所以就不一一介绍了,就算介绍了你也不一定认识!"},
            {"小翠", "小玉", "小群", "小莫", "..."},
            {"小染", "小静", "小莉", "小华","..."}
    };

    public static final String BOOK_NAME = "book_name";
    public static final String FIGURE_NAME = "figure_name";

}

下载链接:点击下载案例

最后再贴一个常用的完整的小Demo(点击第一条时,其他条目都关闭):

安卓 ExpandableListView二级列表使用手册_第3张图片

1.主函数:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.Toast;

public class MainActivity extends Activity {

    private ExpandableListView expandableListView;
    String[] groupNames = { "大陆明星", "香港明星", "美国明星" };
    String[][] childNames = new String[][] { { "刘涛", "胡歌", "范冰冰" },
            { "成龙", "周润发", "张国荣", "陈小春", "刘德华" },
            { "史泰龙", "施瓦辛格", "奥黛丽·赫本", "安吉丽娜朱莉" } };

    int[][] childIcons = new int[][] {
            { R.drawable.ad, R.drawable.ae, R.drawable.af },
            { R.drawable.al, R.drawable.am, R.drawable.an, R.drawable.ao,
                    R.drawable.ag },
            { R.drawable.ad, R.drawable.ae, R.drawable.af, R.drawable.bg } };
    private Drawable[] groupIcons;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 添加资源
        groupIcons = new Drawable[] {
                getResources().getDrawable(R.drawable.aa),
                getResources().getDrawable(R.drawable.ab),
                getResources().getDrawable(R.drawable.ac) };

        expandableListView = (ExpandableListView) findViewById(R.id.elv);

        // 设置数据适配器
        expandableListView.setAdapter(new MyExpandableAdapter(this, groupNames,
                childNames, groupIcons, childIcons));
        expandableListView
                .setOnGroupExpandListener(new OnGroupExpandListener() {

                    @Override
                    public void onGroupExpand(int groupPosition) {
                        // 当打开的时候,设置小图标为反向
                        // expandableListView.setGroupIndicator(getResources()
                        // .getDrawable(R.drawable.ic_launcher2));

                        // 当打开自己的时候,关闭别人
                        for (int i = 0; i < groupNames.length; i++) {
                            if (groupPosition != i) {
                                // 关闭
                                expandableListView.collapseGroup(i);
                            }
                        }
                    }
                });
        /**
         * 监听点击了哪个孩子
         */
        expandableListView.setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick(ExpandableListView parent, View v,
                                        int groupPosition, int childPosition, long id) {
                String string = childNames[groupPosition][childPosition];
                Toast.makeText(MainActivity.this, string, Toast.LENGTH_SHORT).show();
                // 是否消费(处理)该点击事件
                return true;
            }
        });
        /**
         * 组的点击事件
         */
        expandableListView.setOnGroupClickListener(new OnGroupClickListener() {

            @Override
            public boolean onGroupClick(ExpandableListView parent, View v,
                                        int groupPosition, long id) {
                Toast.makeText(MainActivity.this,
                        "第" + groupPosition + "组被点击了", Toast.LENGTH_SHORT).show();
                return false;
            }
        });
        // expandableListView
        // .setOnGroupCollapseListener(new OnGroupCollapseListener() {
        // @Override
        // public void onGroupCollapse(int groupPosition) {
        // // 当打开的时候,设置小图标为反向
        // expandableListView.setGroupIndicator(getResources()
        // .getDrawable(R.drawable.ic_launcher));
        // }
        // });
    }
}

2.适配器:

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MyExpandableAdapter extends BaseExpandableListAdapter {
	private Context context;
	private String[] groupNames;
	private Drawable[] groupIcon;
	private int[][] childIcons;
	private String[][] childNames;

	public MyExpandableAdapter(Context context, String[] groupNames,
			String[][] childNames, Drawable[] groupIcon, int[][] childIcons) {
		this.context = context;
		this.groupNames = groupNames;
		this.groupIcon = groupIcon;
		this.childNames = childNames;
		this.childIcons = childIcons;
	}

	/**
	 * 获取孩子的内容
	 */
	@Override
	public Object getChild(int groupPosition, int childPosition) {
		return childNames[groupPosition][childPosition];
	}

	/**
	 * 返回孩子的id
	 */
	@Override
	public long getChildId(int groupPosition, int childPosition) {
		return childPosition;
	}

	/**
	 * 孩子的布局视图
	 */
	@Override
	public View getChildView(int groupPosition, int childPosition,
			boolean isLastChild, View convertView, ViewGroup parent) {
		View view = View.inflate(context, R.layout.child_item, null);
		ImageView iv_child = (ImageView) view.findViewById(R.id.iv_child);
		TextView tv_child = (TextView) view.findViewById(R.id.tv_child);
		iv_child.setImageResource(childIcons[groupPosition][childPosition]);
		tv_child.setText(childNames[groupPosition][childPosition]);
		return view;
	}

	@Override
	public View getGroupView(int groupPosition, boolean isExpanded,
			View convertView, ViewGroup parent) {
		View view = View.inflate(context, R.layout.group_item, null);
		ImageView iv_group = (ImageView) view.findViewById(R.id.iv_group);
		TextView tv_group = (TextView) view.findViewById(R.id.tv_group);
		// 获取组的图标
		iv_group.setImageDrawable(groupIcon[groupPosition]);
		tv_group.setText(groupNames[groupPosition]);
		return view;
	}

	/**
	 * 返回每一组孩子的个数
	 */
	@Override
	public int getChildrenCount(int groupPosition) {
		// 先获取孩子所在数组,然后获取每一组的长度
		return childNames[groupPosition].length;
	}

	/**
	 * 返回组的内容
	 */
	@Override
	public Object getGroup(int groupPosition) {
		return groupNames[groupPosition];
	}

	/**
	 * 获取组的个数
	 */
	@Override
	public int getGroupCount() {
		return groupNames.length;
	}

	/**
	 * 获取组的id
	 */
	@Override
	public long getGroupId(int groupPosition) {
		return groupPosition;
	}

	/**
	 * 是否有唯一的id
	 */
	@Override
	public boolean hasStableIds() {
		return true;
	}

	/**
	 * 孩子是否可选
	 */
	@Override
	public boolean isChildSelectable(int groupPosition, int childPosition) {
		return true;
	}

}

3.布局:

activity_main.xml:



    

child_item.xml




    

    

group_item.xml




    

    

 

你可能感兴趣的:(Android控件的功能)