Android ExpandableListView自定义二级列表

实现功能:自定义列表样式(一级列表及二级列表子项分别设置不同图标;左侧时间线随列表展开而延伸,最后一项时间线隐藏)
效果图:


Android ExpandableListView自定义二级列表_第1张图片
image.png

布局分析:
上方日期控件省略(用的自带的日期控件,希望推荐一款美观实用的,多谢);
列表:红色框为一级列表(包括顶部是查询时间+左边线条+列表标题),黄色框为二级列表(左边线条+三个子项)


Android ExpandableListView自定义二级列表_第2张图片
image.png

代码:
PageHistoryActivity.java

package com.andbase.patrol.gtDemo.activity.pages.newPages;

import android.app.DatePickerDialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.DatePicker;
import android.widget.ExpandableListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.ab.activity.AbActivity;
import com.andbase.R;
import com.andbase.global.MyApplication;
import com.andbase.patrol.gtDemo.adapter.pagesAdapter.newPagesAdapter.PageHistoryAdapter;
import com.andbase.patrol.gtDemo.model.ElGroupListDemo;
import com.andbase.patrol.gtDemo.util.CustomDatePicker;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * author:lmx
 * date:2018/3/10
 * description:历史任务--日期控件、折叠列表
 */
//public class PageHistoryActivity extends AbActivity  implements View.OnClickListener {
public class PageHistoryActivity extends AbActivity{

    private MyApplication application;
    //日期控件
    private RelativeLayout selectDateStart,selectDateEnd;
    private TextView currentDateStart,currentDateEnd;
    private CustomDatePicker customDatePicker1,customDatePicker2;
    //折叠列表
    private ExpandableListView mExpandableListView = null;
    // 列表数据
    private List mGroupNameList = null;
    private List mGroupTimeList = null;
    private List> mItemNameList = null;
    // 适配器
    private PageHistoryAdapter mAdapter = null;

//    //demo 折叠列表一级列表不同布局
    private PageHistoryActivity context;
//    private ExpandableListView mExpandableListView;
//    private List mGroupNameList = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setAbContentView(R.layout.newpages_activity_history_demo);
        application = (MyApplication)abApplication;

        //加载不同布局
        this.mExpandableListView = (ExpandableListView) findViewById(R.id.elHistoryList);
        context = this;


        //开始日期
        selectDateStart = (RelativeLayout) findViewById(R.id.rlSelectDateStart);
//        selectDateStart.setOnClickListener(this);
        currentDateStart = (TextView) findViewById(R.id.tvCurrentDateStart);
        //结束日期
        selectDateEnd = (RelativeLayout) findViewById(R.id.rlSelectDateEnd);
//        selectDateEnd.setOnClickListener(this);
        currentDateEnd = (TextView) findViewById(R.id.tvCurrentDateEnd);

        //日期选择
//        initDatePicker();


        /**
         * new 自带控件
         */
        currentDateStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DatePickerDialog(PageHistoryActivity.this,new DatePickerDialog.OnDateSetListener(){
                    @Override
                    public void  onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth){

                        String theDate = String.format("%d-%d-%d",year,monthOfYear+1,dayOfMonth);
                        System.out.println(theDate);
                        currentDateStart.setText(theDate);
                    }
                },2018,1,1).show();//月份从零开始,故默认日期月份较实际月份+1
            }
        });

        currentDateEnd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DatePickerDialog(PageHistoryActivity.this,new DatePickerDialog.OnDateSetListener(){
                    @Override
                    public void  onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth){

                        String theDate = String.format("%d-%d-%d",year,monthOfYear+1,dayOfMonth);
                        System.out.println(theDate);
                        currentDateEnd.setText(theDate);
                    }
                },2018,1,1).show();//月份从零开始,故默认日期月份较实际月份+1
            }
        });


        //获取实例-折叠列表
        mExpandableListView = (ExpandableListView) findViewById(R.id.elHistoryList);
        mExpandableListView.setGroupIndicator(null);
        // 初始化数据
        initData();

//        // 为ExpandableListView设置Adapter
//        mAdapter = new PageHistoryAdapter(this, mGroupNameList, mGroupTimeList, mItemNameList);
//        mExpandableListView.setAdapter(mAdapter);

        // 监听组点击
        mExpandableListView.setSelector(new ColorDrawable(Color.TRANSPARENT));//去除点击后出现的黄色背景
        mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v,
                                        int groupPosition, long id) {

                mExpandableListView.setSelector(new ColorDrawable(Color.TRANSPARENT));
                if (mGroupNameList.get(groupPosition).isEmpty()) {
                    return true;
                }
                return false;
            }
        });

        // 监听每个分组里子控件的点击事件
        mExpandableListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                        int childPosition, long id) {

                mExpandableListView.setSelector(new ColorDrawable(Color.TRANSPARENT));
                Toast.makeText(PageHistoryActivity.this,
                        mAdapter.getGroup(groupPosition) + ":"
                                +  mAdapter.getChild(groupPosition, childPosition) ,
                        Toast.LENGTH_SHORT).show();

                return false;

            }
        });


    }

    /**
     * 日期选择
     */
    private void initDatePicker() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA);
        String now = sdf.format(new Date());
        currentDateStart.setText(now.split(" ")[0]);//显示当前日期
        currentDateEnd.setText(now);//显示当前日期、时分

//        currentDateStart.setText("请选择开始日期");
//        currentDateEnd.setText("请选择结束日期");

        customDatePicker1 = new CustomDatePicker(this, new CustomDatePicker.ResultHandler() {
            @Override
            public void handle(String time) { // 回调接口,获得选中的时间
                currentDateStart.setText(time.split(" ")[0]);
            }
        }, "2010-01-01 00:00", now); // 初始化日期格式请用:yyyy-MM-dd HH:mm,否则不能正常运行
        customDatePicker1.showSpecificTime(false); // 不显示时和分
        customDatePicker1.setIsLoop(true); // 允许循环滚动

        customDatePicker2 = new CustomDatePicker(this, new CustomDatePicker.ResultHandler() {
            @Override
            public void handle(String time) { // 回调接口,获得选中的时间
                currentDateEnd.setText(time.split(" ")[0]);
            }
        }, "2010-01-01 00:00", now); // 初始化日期格式请用:yyyy-MM-dd HH:mm,否则不能正常运行
        customDatePicker2.showSpecificTime(false); // 不显示时和分
        customDatePicker2.setIsLoop(true); // 允许循环滚动
    }

    /**
     * 折叠列表
     */
    //初始化数据
    private void initData(){

        //查询时间
        mGroupTimeList = new ArrayList();
        mGroupTimeList.add("2018-03-12");
        mGroupTimeList.add("2018-03-13");
        mGroupTimeList.add("2018-03-14");
        mGroupTimeList.add("");

        // 组名
        mGroupNameList = new ArrayList();
        mGroupNameList.add("外操巡检线路1");
        mGroupNameList.add("工艺巡检线路1");
        mGroupNameList.add("工艺巡检线路2");
        mGroupNameList.add("外操巡检线路2");

        mItemNameList = new  ArrayList>();
        // 外操巡检线路1
        List itemList = new ArrayList();
        itemList.add("区域:区域一");
        itemList.add("类别:A类");
        itemList.add("等级:一级");
        mItemNameList.add(itemList);
        // 工艺巡检线路1
        itemList = new ArrayList();
        itemList.add("区域:区域二");
        itemList.add("类别:A类");
        itemList.add("等级:一级");
        mItemNameList.add(itemList);
        // 工艺巡检线路2
        itemList = new ArrayList();
        itemList.add("区域:区域三");
        itemList.add("类别:A类");
        itemList.add("等级:一级");
        mItemNameList.add(itemList);
        // 外操巡检线路2
        itemList = new ArrayList();
        itemList.add("区域:区域四");
        itemList.add("类别:A类");
        itemList.add("等级:一级");
        mItemNameList.add(itemList);

       // 为ExpandableListView设置Adapter
        ExpandableListView mExpandableListView = (ExpandableListView) findViewById(R.id.elHistoryList);
        mAdapter = new PageHistoryAdapter(context, mGroupNameList, mGroupTimeList, mItemNameList);
        mExpandableListView.setAdapter(mAdapter);
    }
}

newpages_activity_history_demo.xml




    
    

        

        

            

        

    

    

    
    

        

        

        

            

        

    

    

    
    

        

        

        

            

        

    

    

    
    


PageHistoryAdapter.java

package com.andbase.patrol.gtDemo.adapter.pagesAdapter.newPagesAdapter;

import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.andbase.R;
import com.andbase.patrol.gtDemo.activity.pages.newPages.PageHistoryActivity;

import java.util.List;

/**
 * author:lmx
 * date:2018/3/10
 * description:折叠列表
 */

public class PageHistoryAdapter extends BaseExpandableListAdapter {
    private PageHistoryActivity mContext = null;
    private List mGroupTimeList = null;
    private List mGroupList = null;//线路名
    private List> mItemList = null;
    //线路不同布局
    private final int Group_TYPE = 2;
    private final int Group_1 = 0;
    private final int Group_2 = 1;
    //子项不同布局
    private final int VIEW_TYPE = 3;
    private final int TYPE_1 = 0;
    private final int TYPE_2 = 1;
    private final int TYPE_3 = 2;

    public PageHistoryAdapter(PageHistoryActivity context, List groupList, List groupTimeList,
                                       List> itemList) {
        this.mContext = context;
        this.mGroupList = groupList;
        this.mGroupTimeList = groupTimeList;
        this.mItemList = itemList;
    }

    /**
     * 获取组的个数
     *
     * @return
     * @see android.widget.ExpandableListAdapter#getGroupCount()
     */
    @Override
    public int getGroupCount() {
        return mGroupList.size();
    }

    /**
     * 获取指定组中的子元素个数
     *
     * @param groupPosition
     * @return
     * @see android.widget.ExpandableListAdapter#getChildrenCount(int)
     */
    @Override
    public int getChildrenCount(int groupPosition) {
        return mItemList.get(groupPosition).size();
    }

    /**
     * 获取指定组中的数据
     *
     * @param groupPosition
     * @return
     * @see android.widget.ExpandableListAdapter#getGroup(int)
     */
    @Override
    public String getGroup(int groupPosition) {
        return mGroupList.get(groupPosition);
    }

    /**
     * 获取指定组中的指定子元素数据。
     *
     * @param groupPosition
     * @param childPosition
     * @return
     * @see android.widget.ExpandableListAdapter#getChild(int, int)
     */
    @Override
    public String getChild(int groupPosition, int childPosition) {
        return mItemList.get(groupPosition).get(childPosition);
    }

    /**
     * 获取指定组的ID,这个组ID必须是唯一的
     *
     * @param groupPosition
     * @return
     * @see android.widget.ExpandableListAdapter#getGroupId(int)
     */
    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    /**
     * 获取指定组中的指定子元素ID
     *
     * @param groupPosition
     * @param childPosition
     * @return
     * @see android.widget.ExpandableListAdapter#getChildId(int, int)
     */
    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    /**
     * 线路的两种布局
     *
     * @param groupPosition
     * @return
     */
    public int getGroupViewType(int groupPosition) {
        int g = groupPosition;
        if (g % 2 == 0) { //偶数
            return Group_1;
        }
//        else if (g == 1) {
//            return Group_2;
//        }
        else {
            return Group_2;
        }
    }

    /**
     * 子项的三种布局
     *
     * @param childPosition
     * @return
     */
    public int getItemViewType(int childPosition) {
        int p = childPosition;
        if (p == 0) {
            return TYPE_1;
        }
        else if (p == 1) {
            return TYPE_2;
        } else if (p == 2) {
            return TYPE_3;
        }
        else {
            return TYPE_1;
        }
    }

    /**
     * 获取显示指定组的视图对象
     *
     * @param groupPosition 组位置
     * @param isExpanded    该组是展开状态还是伸缩状态
     * @param convertView   重用已有的视图对象
     * @param parent        返回的视图对象始终依附于的视图组
     * @return
     * @see android.widget.ExpandableListAdapter#getGroupView(int, boolean, android.view.View,
     * android.view.ViewGroup)
     */
    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
                             ViewGroup parent) {

        GroupHolder groupHolder = null;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.newpages_history_expandlist_group_item_demo, null);
            groupHolder = new GroupHolder();
            //获取时间显示
            groupHolder.rlGroupBox = (RelativeLayout) convertView.findViewById(R.id.rlGroupBox);
            groupHolder.ivGroupTimeImg = (ImageView) convertView.findViewById(R.id.ivGroupTimeImg);
            groupHolder.tvGroupTime = (TextView) convertView.findViewById(R.id.tvGroupTime);
            //标题行
            groupHolder.llListHeader = (LinearLayout) convertView.findViewById(R.id.llListHeader);
            groupHolder.tvGroupName = (TextView) convertView.findViewById(R.id.tvGroupName);
            groupHolder.ivGroupTilleImg = (ImageView) convertView.findViewById(R.id.ivGroupTilleImg);
            groupHolder.ivElImg = (ImageView) convertView.findViewById(R.id.ivElImg);
            groupHolder.ivLeftGroupLine = (ImageView) convertView.findViewById(R.id.ivLeftGroupLine);
            convertView.setTag(groupHolder);
        } else {
            groupHolder = (GroupHolder) convertView.getTag();
        }

        if (isExpanded) {//展开
            groupHolder.ivElImg.setImageResource(R.drawable.history_expand_top_open);
            //展开直角
            groupHolder.llListHeader.setBackgroundResource(R.drawable.history_ellist_top_bg_demo);
        } else {//折叠
            groupHolder.ivElImg.setImageResource(R.drawable.history_expand_top_close);
            //折叠圆角
            groupHolder.llListHeader.setBackgroundResource(R.drawable.history_ellist_top_bg_close_demo);
        }
        //显示线路名
        groupHolder.tvGroupName.setText(mGroupList.get(groupPosition));
        //显示时间:时间若为空,则显示区域隐藏
        if(!"".equals(mGroupTimeList.get(groupPosition))){
            groupHolder.tvGroupTime.setText(mGroupTimeList.get(groupPosition));
        }else{
            groupHolder.rlGroupBox.setVisibility(View.GONE);
        }
        //标题图片:偶数行显示外操图片,奇数行显示工艺图片
        if(groupPosition % 2 == 0){
            groupHolder.ivGroupTilleImg.setImageResource(R.drawable.history_expand_top_wc);
        }else {
            groupHolder.ivGroupTilleImg.setImageResource(R.drawable.history_expand_top_gy);
        }
        //最后一项左侧线隐藏
        if("".equals(mGroupTimeList.get(groupPosition)) || "2018-03-14".equals(mGroupTimeList.get(groupPosition))){
            groupHolder.ivLeftGroupLine.setBackgroundColor(Color.TRANSPARENT);

        }else{
            groupHolder.ivLeftGroupLine.setBackgroundColor(Color.parseColor("#33cc99"));
        }

        return convertView;
    }

    /**
     * 获取一个视图对象,显示指定组中的指定子元素数据。
     *
     * @param groupPosition 组位置
     * @param childPosition 子元素位置
     * @param isLastChild   子元素是否处于组中的最后一个
     * @param convertView   重用已有的视图(View)对象
     * @param parent        返回的视图(View)对象始终依附于的视图组
     * @return
     * @see android.widget.ExpandableListAdapter#getChildView(int, int, boolean, android.view.View,
     * android.view.ViewGroup)
     */
    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
                             View convertView, ViewGroup parent) {

        ItemHolder itemHolder = null;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.newpages_history_expandlist_item_area_demo, null);
            itemHolder = new ItemHolder();
            //子项
            itemHolder.llListHeader = (LinearLayout)convertView.findViewById(R.id.llListHeader);
            itemHolder.ivItemIconImg = (ImageView) convertView.findViewById(R.id.ivItemIconImg);
            itemHolder.ivLeftItemLine = (ImageView) convertView.findViewById(R.id.ivLeftItemLine);
            itemHolder.tvItemName = (TextView) convertView.findViewById(R.id.tvItemName);

            convertView.setTag(itemHolder);
        } else {
            itemHolder = (ItemHolder) convertView.getTag();
        }

        //子项数据
        itemHolder.tvItemName.setText(mItemList.get(groupPosition).get(childPosition));
        //子项图片
        switch (childPosition){
            case 0:
                itemHolder.ivItemIconImg.setImageResource(R.drawable.history_expand_item_area);
                itemHolder.llListHeader.setBackgroundResource(R.drawable.history_ellist_content_bg_close_demo);
                break;
            case 1:
                itemHolder.ivItemIconImg.setImageResource(R.drawable.history_expand_item_sort);
                itemHolder.llListHeader.setBackgroundResource(R.drawable.history_ellist_content_bg_close_demo);
                break;
            case 2:
                itemHolder.ivItemIconImg.setImageResource(R.drawable.history_expand_item_level);
                //最后一项底部呈圆角
                itemHolder.llListHeader.setBackgroundResource(R.drawable.history_ellist_content_bg_demo);
                break;
        }
        //最后一项左侧线隐藏
        if("".equals(mGroupTimeList.get(groupPosition)) || "2018-03-14".equals(mGroupTimeList.get(groupPosition))){
            itemHolder.ivLeftItemLine.setBackgroundColor(Color.TRANSPARENT);

        }else{
            itemHolder.ivLeftItemLine.setBackgroundColor(Color.parseColor("#33cc99"));
        }
      return convertView;
    }

    /**
     * 组和子元素是否持有稳定的ID,也就是底层数据的改变不会影响到它们。
     *
     * @return
     * @see android.widget.ExpandableListAdapter#hasStableIds()
     */
    @Override
    public boolean hasStableIds() {
        return true;
    }

    /**
     * 是否选中指定位置上的子元素。
     *
     * @param groupPosition
     * @param childPosition
     * @return
     * @see android.widget.ExpandableListAdapter#isChildSelectable(int, int)
     */
    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }
    //线路两种布局
    class GroupHolder {
        public RelativeLayout rlGroupBox;//显示时间区域
        public TextView tvGroupTime;//时间
        public ImageView ivGroupTimeImg;//时间线图片
        public TextView tvGroupName;//线路名
        public ImageView ivElImg;//折叠标志图片
        public ImageView ivGroupTilleImg;//标题左侧图片
        public ImageView ivLeftGroupLine;//左侧线
        private LinearLayout llListHeader;//边角
    }
    //子项布局
    class ItemHolder {
        public ImageView ivItemIconImg;//图片
        public TextView tvItemName;//内容
        public ImageView ivLeftItemLine;//左侧线
        private LinearLayout llListHeader;//边角
    }

}

newpages_history_expandlist_group_item_demo.xml




    
    

        

        

    

    

        

        

            
            

            

            
            

                
                

            

        

    


newpages_history_expandlist_item_area_demo.xml




    

    

            
        

            

        


history_ellist_top_bg_close_demo.xml



    
    
    
    
    
    

history_ellist_top_bg_demo.xml



    
    
   
    
    
    

history_ellist_content_bg_close_demo.xml




    

    

    


history_ellist_content_bg_demo.xml



    
    
    
    
    
    
    
    
    

color.xml

#33cc99
#33ccff
Android ExpandableListView自定义二级列表_第3张图片
image.png
Android ExpandableListView自定义二级列表_第4张图片
image.png

完。

你可能感兴趣的:(Android ExpandableListView自定义二级列表)