【Android】ExPandableListView实现时间轴

作者: 吾非言 | 来源:发表于2017-09-03 22:40 被阅读304次

    作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc

    本文选自书客创作平台第39篇文章。阅读原文

    书客创作

    时间轴效果无论是移动端还是Web端,都是十分常见的功能之一,主要用来按照时间或相应的步骤来说明或展示相应的信息。在移动端实现时间轴效果的方式也非常多,那么今天就说说如何利用ExPandableListView来实现时间轴效果。

    对于ExPandableListView基本使用方法,可以通过
    【Android】ExpandableListView的使用这篇文章进行了解。

    时间轴效果图

    分析:从纵向来看整个时间轴被划分成左右两个部分,但是如果要使用ExPandableListView实现这样的效果,就无法通过左右两个部分进行分析了。因为ExPandableListView是二级列表。那么从横向来看,确实可以将其划分成二级列表的模式,例如可以将竖线之上的部分划分为一级列表,将竖线平行部分划分为二级列表,这样就可以将该时间轴按照ExPandableListView的思想来设计了。

    一、首先是XML布局

    1、在页面布局文件activity_timeline.xml中添加ExPandableListView控件。

    <ExpandableListView
            android:id="@+id/expandlist"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:cacheColorHint="#00000000"
            android:divider="@null"
            android:listSelector="@android:color/transparent"
            android:scrollbars="none" />
    

    2、设置一级列表布局

    <?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="wrap_content"
        android:background="@color/white">
    
        <TextView
            android:id="@+id/tv_step"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerVertical="true"
            android:gravity="end"
            android:text="@string/app_name"
            android:textColor="#555"
            android:textSize="16sp" />
    
        <ImageView
            android:id="@+id/img_dot"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_margin="10dp"
            android:layout_toEndOf="@id/tv_step"
            android:layout_toRightOf="@id/tv_step"
            android:contentDescription="@null"
            android:src="@drawable/guide_dot_choose" />
    
        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toEndOf="@id/img_dot"
            android:layout_toRightOf="@id/img_dot"
            android:text="@string/app_name"
            android:textColor="@color/colorTitle"
            android:textSize="16sp" />
    </RelativeLayout>
    
    一级列表布局效果图

    3、二级列表布局

    <?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="wrap_content"
        android:background="@color/white"
        android:gravity="center_vertical">
    
        <View
            android:id="@+id/view_line"
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:layout_marginLeft="95dp"
            android:layout_marginStart="95dp"
            android:background="#ccc" />
    
        <TextView
            android:id="@+id/tv_desc"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="3dp"
            android:layout_marginEnd="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginStart="10dp"
            android:layout_marginTop="3dp"
            android:lineSpacingExtra="3dp"
            android:lines="1"
            android:text="@string/hello_world"
            android:textColor="#888" />
    
    </LinearLayout>
    
    二级列表布局效果图

    二、设置列表数据对象

    1、一级列表数据对象,一级列表数据对象类包含对应二级列表数据集。

    public class TimeLineGroupData {
        private String gtitle;
        private String gstep;
        /**
         * 二级Item数据列表
         **/
        private List<TimeLineChildData> childList;
    
        public String getGtitle() {
            return gtitle;
        }
        public void setGtitle(String gtitle) {
            this.gtitle = gtitle;
        }
        public String getGstep() {
            return gstep;
        }
        public void setGstep(String gstep) {
            this.gstep = gstep;
        }
        public List<TimeLineChildData> getChildList() {
            return childList;
        }
        public void setChildList(List<TimeLineChildData> childList) {
            this.childList = childList;
        }
    }
    

    2、二级列表对象。

    public class TimeLineChildData {
        /**
         * 描述信息
         **/
        private String desc;
    
        public String getDesc() {
            return desc;
        }
        public void setDesc(String desc) {
            this.desc = desc;
        }
    }
    

    三、自定义Adapter

    自定义ExPandableListView的适配器需要继承BaseExpandableListAdapter 。并实现一级列表和二级列表的相关处理方法。

    public class TimeLineExpAdapter extends BaseExpandableListAdapter {
        private LayoutInflater inflater = null;
        private List<TimeLineGroupData> groupList = new ArrayList<>();
    
        /**
         * 构造方法
         */
        public TimeLineExpAdapter(Context context, List<TimeLineGroupData> group_list) {
            this.groupList = group_list;
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
    
        // 刷新数据
        public void flashData(List<TimeLineGroupData> datas) {
            this.groupList = datas;
            this.notifyDataSetChanged();
        }
    
        /**
         * 返回一级Item总数
         */
        @Override
        public int getGroupCount() {
            return groupList.size();
        }
    
        /**
         * 返回二级Item总数
         */
        @Override
        public int getChildrenCount(int groupPosition) {
            if (groupList.get(groupPosition).getChildList() == null) {
                return 0;
            } else {
                return groupList.get(groupPosition).getChildList().size();
            }
        }
    
        /**
         * 获取一级Item内容
         */
        @Override
        public Object getGroup(int groupPosition) {
            return groupList.get(groupPosition);
        }
    
        /**
         * 获取二级Item内容
         */
        @Override
        public Object getChild(int groupPosition, int childPosition) {
            return groupList.get(groupPosition).getChildList().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) {
            GroupViewHolder holder;
            if (convertView == null) {
                holder = new GroupViewHolder();
                convertView = inflater.inflate(R.layout.activity_timeline_group_item, parent, false);
                holder.stepTv = (TextView) convertView.findViewById(R.id.tv_step);
                holder.titleTv = (TextView) convertView.findViewById(R.id.tv_title);
                convertView.setTag(holder);
            } else {
                holder = (GroupViewHolder) convertView.getTag();
            }
            holder.titleTv.setText(groupList.get(groupPosition).getGstep());
            holder.stepTv.setText(groupList.get(groupPosition).getGtitle());
            return convertView;
        }
    
        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
            ChildViewHolder viewHolder;
            TimeLineChildData entity = (TimeLineChildData) getChild(groupPosition, childPosition);
            if (convertView != null) {
                viewHolder = (ChildViewHolder) convertView.getTag();
            } else {
                viewHolder = new ChildViewHolder();
                convertView = inflater.inflate(R.layout.activity_timeline_child_item, parent, false);
                viewHolder.descTv = (TextView) convertView.findViewById(R.id.tv_desc);
                convertView.setTag(viewHolder);
            }
            viewHolder.descTv.setText(entity.getDesc());
            return convertView;
        }
    
        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return false;
        }
    
        private class GroupViewHolder {
            TextView titleTv, stepTv;
        }
    
        private class ChildViewHolder {
            TextView descTv;
        }
    }
    

    四、Activity实现

    public class TimeLineActivity extends AppCompatActivity {
        private ExpandableListView expandlistView;
        private TimeLineExpAdapter statusAdapter;
        private List<TimeLineGroupData> groupList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_timeline);
    
            initView();
            setListData();
            setAdapter();
            initExpandListView();
        }
    
        // 初始化控件
        private void initView() {
            expandlistView = (ExpandableListView) findViewById(R.id.expandlist);
        }
    
        /**
         * 自定义setAdapter
         */
        private void setAdapter() {
            if (statusAdapter == null) {
                statusAdapter = new TimeLineExpAdapter(this, groupList);
                expandlistView.setAdapter(statusAdapter);
            } else {
                statusAdapter.flashData(groupList);
            }
        }
    
        /**
         * 初始化可拓展列表
         */
        private void initExpandListView() {
            expandlistView.setGroupIndicator(null); // 去掉默认带的箭头
            expandlistView.setSelection(0);// 设置默认选中项
    
            // 遍历所有group,将所有项设置成默认展开
            int groupCount = expandlistView.getCount();
            for (int i = 0; i < groupCount; i++) {
                expandlistView.expandGroup(i);
            }
    
            expandlistView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
                @Override
                public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                    return true;
                }
            });
        }
    
        // 列表赋值
        private List<TimeLineGroupData> setListData() {
            if (groupList == null) {
                groupList = new ArrayList<>();
                // 一级列表数据
                for (int i = 0; i < 8; i++) {
                    TimeLineGroupData timeLineGroupData = new TimeLineGroupData();
                    timeLineGroupData.setGtitle("第" + i + "步");
                    timeLineGroupData.setGstep("第" + i + "步的标题");
                    // 二级列表数据
                    ArrayList<TimeLineChildData> childDataList = new ArrayList<>();
                    for (int j = 0; j < 2; j++) {
                        TimeLineChildData timeLineChildData = new TimeLineChildData();
                        timeLineChildData.setDesc("第" + i + "步描述" + j + "实现时间轴效果");
                        childDataList.add(timeLineChildData);
                    }
                    timeLineGroupData.setChildList(childDataList);
                    groupList.add(timeLineGroupData);
                }
            }
            return groupList;
        }
    }
    

    到这里一个简单的时间轴效果就实现了,但是有几个地方需要注意:

    注意1:要收到设置时间轴为展开状态。

     // 遍历所有group,将所有项设置成默认展开
    int groupCount = expandlistView.getCount();
    for (int i = 0; i < groupCount; i++) {
        expandlistView.expandGroup(i);
    }
    

    注意2:去掉默认带的箭头

    expandlistView.setGroupIndicator(null);
    

    Github地址
    阅读原文


    微信公众号:书客创作

    相关文章

      网友评论

        本文标题:【Android】ExPandableListView实现时间轴

        本文链接:https://www.haomeiwen.com/subject/vmgjjxtx.html