Android开发之ExpandableListView可拓展列表和子item左滑结合

Hello!各位大神好,这是我的第一篇博客,大二学生初学安卓还不到几个月,所以希望不足之处能够多多指教。
在Android开发中,我们经常会遇到点击,展开,可拓展列表的使用,同时可恶的产品经理还要求你在可拓展列表下增加左滑按钮的功能。那这两个功能如何具体相互结合实现呢?接下来先看一下结果效果图。可拓展列表+左滑Item
怎么样?是不是你想要的呢?
接下来我们分两步来看一下这个功能。
首先是可拓展列表ExpandableListView的功能实现。
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <com.easeplan.com.view.SwipeExpandableListView
            android:id="@+id/exlist_lol"
            android:childIndicator="@null"
            android:groupIndicator="@null"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:childDivider="#ffffff"/>
</LinearLayout>

有注意到,我调用的SwipeExpandableListView是一个用java自定义的布局,由于代码太长我就不发出来了,有需要的小伙伴可在下面留言。
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">
	<ImageView
	    android:id="@+id/img_icon1"
	    android:layout_width="64dp"
	    android:layout_height="58dp"
	    android:src="@mipmap/ic_launcher"
	    android:focusable="false"
	    android:paddingLeft="6dp"
	    />
	<TextView
	    android:id="@+id/tv_group_name"
	    android:layout_width="match_parent"
	    android:layout_height="56dp"
	    android:gravity="center_vertical"
	    android:paddingLeft="12dp"
	    android:text="AP"
	    android:textStyle="bold"
	    android:textSize="20sp" />
 </LinearLayout>

可以看到,在这个布局中,我是设置了一个图片作为头像,还有文字作为标题。而图片可以换成你想要的,但是也可以在java代码中设置。而我是选择了在java代码中设置。
接着是左滑按钮的实现。
item_exlist_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.easeplan.com.view.SwipeItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<!--子列表布局-->
	<FrameLayout
	    android:layout_width="match_parent"
	    android:layout_height="match_parent">
		<LinearLayout
		    android:layout_width="270dp"
		    android:layout_height="59dp"
		    android:orientation="horizontal"
		    android:layout_gravity="right"
		    android:id="@+id/linear">
		    <!--垂直布局-->
		   <LinearLayout
		        android:layout_width="270dp"
		        android:layout_height="59dp"
		        android:orientation="vertical"
		        android:background="@drawable/shape2"
		        android:id="@+id/id_front">
		    <TextView
		        android:id="@+id/tv_name"
		        android:layout_width="270dp"
		        android:layout_height="wrap_content"
		        android:layout_weight="1"
		        android:focusable="true"
		        android:text="提莫"
		        android:textSize="18sp"
		        android:gravity="left"
		        android:paddingTop="6dp"
		        android:paddingLeft="9dp"
		        android:textColor="#ffffff"/>
		        <TextView
		            android:layout_width="270dp"
		            android:layout_height="wrap_content"
		            android:focusable="true"
		            android:textSize="10sp"
		            android:text="提莫"
		            android:gravity="left"
		            android:paddingBottom="10dp"
		            android:paddingLeft="12dp"
		            android:id="@+id/tv_msg"
		            android:textColor="#ffffff"/>
		    </LinearLayout>
	</LinearLayout>
</FrameLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent">
	    <Button
	        android:id="@+id/stick"
	        android:text="添加到日程"
	        android:textColor="#ffffff"
	        android:textSize="16sp"
	        android:background="#ff8000"
	        android:layout_width="100dp"
	        android:layout_height="match_parent"/>
	    <Button
	        android:id="@+id/delete"
	        android:text="删除"
	        android:textColor="#ffffff"
	        android:textSize="16sp"
	        android:background="#ff0000"
	        android:layout_width="80dp"
	        android:layout_height="match_parent"/>
    </LinearLayout>
</com.easeplan.com.view.SwipeItemLayout>

分析代码可知,我是在子item里面设置了垂直方向上的两行文字,接着在线性布局中设置了两个按钮。需要注意是,左滑布局我仍然用的是一个自定义的布局,需要的可以在下方留言。
好啦,布局文件就这么多,至于drawable、values文件还有注册文件就自己写吧。
接下来看一下java代码吧。。。
实体类GroupBean.java

public class GroupBean extends LitePalSupport {
    private int gId;
    private String gName;//主标题名字
 
    public GroupBean(int gId, String gName) {
        this.gName = gName;
        this.gId=gId;
    }
    public int getgId() {
        return gId;
    }
    public void setgId(int gId) {
        this.gId = gId;
    }
    public String getgName() {
        return gName;
    }
    public void setgName(String gName) {
        this.gName = gName;
    }

}

实体类Item.java

public class Item {
    private String iName;//文字名字
    private String iMsg;//文字信息

    public Item() {
    }

    public Item(String iName,String iMsg) {
        this.iName = iName;
        this.iMsg=iMsg;

    }
    public String getiName() {
        return iName;
    }

    public String getiMsg(){return iMsg;}

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

    public void setiMsg(String iMsg){this.iMsg=iMsg;}
}

适配器MyBaseExpandableListViewAdapter.java

public class MyBaseExpandableListViewAdapter extends BaseExpandableListAdapter {

    private ArrayList<GroupBean> gData;
    private ArrayList<ArrayList<Item>> iData;
    private Context mContext;
    private OnClickListenerEditOrDelete onClickListenerEditOrDelete;
    private boolean text_add=false;

    public MyBaseExpandableListViewAdapter(ArrayList<GroupBean> gData, 				     ArrayList<ArrayList<Item>> iData, Context mContext) {
        this.gData = gData;
        this.iData = iData;
        this.mContext = mContext;
    }
    @Override
    public int getGroupCount() {
        return gData.size();
    }
    @Override
    public int getChildrenCount(int groupPosition) {
        return iData.get(groupPosition).size();
    }
    @Override
    public GroupBean getGroup(int groupPosition) {
        return gData.get(groupPosition);
    }
    @Override
    public Item getChild(int groupPosition, int childPosition) {
        return iData.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 false;
    }

    //返回分组的视图对象
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

        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);//文字
            groupHolder.img_group = (ImageView) convertView.findViewById(R.id.img_icon1);//图片
            convertView.setTag(groupHolder);
        }else{
            groupHolder = (ViewHolderGroup) convertView.getTag();
        }
        //文字与图片显示
        groupHolder.img_group.setImageResource(gData.get(groupPosition).getgId());
        groupHolder.tv_group_name.setText(gData.get(groupPosition).getgName());
        return convertView;
    }

    //取得显示给定分组给定子位置的数据用的视图
    @Override
    public View getChildView( final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        final 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_name);//子列表中上标题
            itemHolder.tv_msg = (TextView) convertView.findViewById(R.id.tv_msg);//子列表中下标题
            itemHolder.linear=convertView.findViewById(R.id.linear);//整个子列表
            itemHolder.delete=(Button)convertView.findViewById(R.id.delete);//删除按钮
            itemHolder.add=(Button)convertView.findViewById(R.id.stick);//添加到日程按钮
            convertView.setTag(itemHolder);
            itemHolder.linear.setOnClickListener(new View.OnClickListener() {//子列表按钮
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(mContext,EventInfoActivity.class);//点击Item可跳转的界面
                    mContext.startActivity(intent);
                }
            });
            itemHolder.delete.setOnClickListener(new View.OnClickListener() {//删除按钮
                @Override
                public void onClick(View v) {//删除对话框
                    AlertDialog alert=new AlertDialog.Builder(mContext).create();
                    alert.setIcon(R.drawable.ic_notifications_black_24dp);
                    alert.setTitle("请问您确定要删除吗?");
                    alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {//点击确定删除后
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            if (onClickListenerEditOrDelete!=null){
                                onClickListenerEditOrDelete.OnClickListenerDelete(groupPosition,childPosition);
                            }
                        }
                    });
                    alert.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    });
                   alert.show();
                }
            });
            itemHolder.add.setOnClickListener(new View.OnClickListener() {//添加到日程按钮
                @Override
                public void onClick(View v) {
                        Toast.makeText(mContext,"添加成功!",Toast.LENGTH_SHORT).show();
                }
            });
        }else{
            itemHolder = (ViewHolderItem) convertView.getTag();
        }
        //子列表文字显示
        itemHolder.tv_name.setText(iData.get(groupPosition).get(childPosition).getiName());
        itemHolder.tv_msg.setText(iData.get(groupPosition).get(childPosition).getiMsg());
        return convertView;
    }

    //设置子列表是否可选中
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
    //自定义Group类
    private static class ViewHolderGroup{
        private TextView tv_group_name;
        private ImageView img_group;
    }
    //自定义Item类
    private static class ViewHolderItem{
        private TextView tv_name;
        private TextView tv_msg;
        private View linear;
        private Button delete;
        private Button add;
    }
    //删除接口
    public interface OnClickListenerEditOrDelete{
        void OnClickListenerDelete(int groupPosition, int position);
    }
    public void setOnClickListenerEditOrDelete(OnClickListenerEditOrDelete onClickListenerEditOrDelete1){
        this.onClickListenerEditOrDelete=onClickListenerEditOrDelete1;
    }

}

碎片Fragment中的代码,具体需要的同学可以改成activity
Fragment_people.java

public class Fragment_people extends Fragment {
  
    private ArrayList<GroupBean> gData = null;//group
    private ArrayList<ArrayList<Item>> iData = null;//item列表
    private ArrayList<Item> lData = null;//item
    
    private Context mContext;//相当于fragment_people.this
    private SwipeExpandableListView exlist_lol;//group
    private MyBaseExpandableListViewAdapter myAdapter = null;//item适配器
  
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.mfragment_people, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mContext = getActivity();
        exlist_lol = (SwipeExpandableListView) getActivity().findViewById(R.id.exlist_lol);
        linear = (View) getActivity().findViewById(R.id.linear);//最近的组织获得实例
        delete = (Button) getActivity().findViewById(R.id.delete);//最近的好友获得实例
        //TODO:这数据是初始化的,动态到时候需要后台连接
        //可拓展列表头部图片和文字定义
        gData = new ArrayList<GroupBean>();
        iData = new ArrayList<ArrayList<Item>>();
        gData.add(new GroupBean(R.mipmap.xiaokui, "学生会秘书处"));
        gData.add(new GroupBean(R.mipmap.yingyu, "大学英语—34班"));
        gData.add(new GroupBean(R.mipmap.chengxuyuan, "鸣黄柳"));
        gData.add(new GroupBean(R.mipmap.xiaohuangren, "bami"));
        //学生会秘书处
        lData = new ArrayList<Item>();
        lData.add(new Item("写策划案", "10月12日-11月05日"));
        lData.add(new Item("社团聚会", "10月20日"));
        iData.add(lData);//因为子列表有多个,所以需要lData.
        //大学英语34班
        lData = new ArrayList<Item>();
        lData.add(new Item("提交作文", "10月18日"));
        lData.add(new Item("阅读第三单元", "10月19日12:00"));
        lData.add(new Item("完成PPT", "11月01日-11月05日"));
        iData.add(lData);
          //鸣黄柳
        lData = new ArrayList<Item>();
        lData.add(new Item("完成数构作业", "12月21日"));
        lData.add(new Item("购买书籍", "12月18日-12月20日"));
        iData.add(lData);
        //bami
        lData = new ArrayList<Item>();
        lData.add(new Item("上吉他课", "11月11日"));
        lData.add(new Item("去兼职", "11月12日12:00"));
        lData.add(new Item("去西门拿快递", "11月11日17:30"));
        iData.add(lData);

        //添加适配器
        myAdapter = new MyBaseExpandableListViewAdapter(gData, iData, mContext);
        exlist_lol.setAdapter(myAdapter);
        //删除操作
        myAdapter.setOnClickListenerEditOrDelete(new MyBaseExpandableListViewAdapter.OnClickListenerEditOrDelete() {
            @Override
            public void OnClickListenerDelete(int groupPosition, int position) {
                Toast.makeText(mContext, "删除成功!", Toast.LENGTH_SHORT).show();
                iData.get(groupPosition).remove(position);//删除选中的某列
                if (iData.get(groupPosition).size() <= 0) {//如果删除后,该组下没成员,那么移除标题和该组的数据集合
                    iData.remove(groupPosition);
                    gData.remove(groupPosition);
                }
                myAdapter.notifyDataSetChanged();//通知Adapter更新数据
            }
        });
        for (int i = 0; i < iData.size(); i++) {//首次加载就全部打开
            exlist_lol.expandGroup(i);
        }
}

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        super.onCreateOptionsMenu(menu, inflater);
        getActivity().getMenuInflater().inflate(R.menu.people_toolbar,menu);
    }
    /**标题栏监听事件*/
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                break;
            case R.id.people_add:
                Intent intent1=new Intent(getActivity(), Contacts_addActivity.class);
                startActivity(intent1);
                break;
            default:
        }
        return super.onOptionsItemSelected(item);
    }

}

注意:以上的图片是自己要添加进drawable文件夹的哦,标题栏的构造也是需要在menu文件夹下定义的哦。
好啦,大概的代码就是这些。代码里面有参考别人的博客,也有自己思考出来,做出来的东西,希望不足之处可以大方指出来呦。。。

版权声明:本文为Johan666原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Johan666/article/details/90341098

智能推荐

说说 Python Django 应用的基础目录结构

通过以下 django-admin 指令创建应用之后,就会生成应用的基础目录结构。 比如,我们建立了一个叫 ‘first’ 的应用,它的目录结构是这样的: 目录或文件 说明 最外层的 first/ 这是新应用的根目录,所有与该应用相关的内容都放在这里。 manage.py 用于管理 Django 项目的命令行工具。 里面一层的 first/ 目录 是一个...

Springboot整合rabbitMQ

依赖: 配置文件application.yml RabbitConfig 消息生产者RabbitProducer 消息消费者RabbitCustomer 通过Controller进行调用 启动项目后调用接口: 结果:...

Thread.join()方法的使用

如果一个线程A执行了thread.join()语句,代表当前线程A等待thread线程终止后才从thread.join()方法返回 并且这个方法具有超时特性,可以添加参数设置 输出结果: jdk中Thread.join()方法的源码(进行了部门调整)   每个线程终止的条件是前驱线程的终止,每个线程等待前驱线程终止后,才从join()方法返回,  当线程终止时,会调用自身的no...

linux服务器部署jenkins笔记

安装jenkins参考文档:https://blog.csdn.net/tomatocc/article/details/83930714 1. 打开jenkins官网:https://jenkins.io/download/ 将war包下载到本地 **ps:**这里要注意的是要下载左边下方的war包,不要下载右边下面的war包。左边是稳定版本,右边是最新版本,建议大家使用稳定版本(我刚开始下载的...

k8s部署elasticsearch集群

百度营销大学     环境准备 我们使用的k8s和ceph环境见: https://blog.51cto.com/leejia/2495558 https://blog.51cto.com/leejia/2499684 ECK简介 Elastic Cloud on Kubernetes,这是一款基于 Kubernetes Operator 模式的新型编排产品,用户可使用该产品在...

猜你喜欢

saas-export项目-AdminLTE介绍与入门

AdminLTE介绍 (1)AdminLTE是什么? AdminLTE是一款建立在bootstrap和jquery之上的开源的模板主题工具 (2)AdminLTE有什么特点? 提供一系列响应的、可重复使用的组件, 并内置了多个模板页面 自适应多种屏幕分辨率,兼容PC和移动端 快速的创建一个响应式的Html5网站 AdminLTE 不但美观, 而且可以免去写很大CSS与JS的工作量 AdminLTE...

MyBatis中ResultMap结果集映射

用于解决属性名和字段名不一致的情况: resultMap 元素是 MyBatis 中最重要最强大的元素。...

编写一个shell

编写shell的过程: 1.从标准输入中读入一个字符串。 2.解析字符串 3.创建一个子进程的执行程序。 4.子进程程序替换。 5.父进程等待子进程退出。...

WEB自动化测试中Xpath定位方法

前言: Xpath是在XML文档中查找信息的一种语言,使用路径表达式来选取XML文档中的节点或节点集,由于XML与HTML结构类似(前者用于传输数据,后者用于显示数据),所以Xpath也常用于查找HTML文档中的节点或节点集。 一  路径表达式: 路径以“/”开始     表示找到满足该绝对路径的元素; 路径以//”开始  ...

力扣困难难度 第4题 寻找两个正序数组的中位数

先看一眼题 我的思路: 设置下标i,j分别用于遍历两个数组,初始值均为0,直到找到两个数组中从小到大的第第length/2个数为止结束循环,length为两个数组长度之和。 ·每次比较nums[i]nums[j],如果前者小则i++,否则j++ ·循环结束时,如果count已经达到length/2,则说明已经找到了中位数,[注意:此时有可能正好其中一个数组遍历完了!所以...