超简单ListView打造的多级展开菜单

最近项目有个需求,需要用到侧边栏的拖出来是一个多级的菜单,但是我们都知道android里面只有二级的expandablelistview这个控件,而且扩展性也不算很好,而项目需求是能够多级展开的,就是有可能扩展到4、5级这样,然后就着手在listview上动文章

效果图

效果图

1.主页

侧边栏用的是v4包的SlidingPaneLayout,里面左右放入fragment填充,但是当右边的fragment内容是viewpager的时候,大家应该都知道,viewpager会和SlidingPaneLayout发生事件冲突,这里我是用网上的方法解决的,大概就是重写SlidingPaneLayout的onInterceptTouchEvent的方法,贴出mainactivity的布局代码

    <com.example.mrchen.custommultiexpanddemo.ui.PagerEnabledSlidingPaneLayout
        android:id="@+id/spl"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/leftfragment"
            android:name="com.example.mrchen.custommultiexpanddemo.fragment.LeftFragment"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="start" >
        </fragment>

        <fragment
            android:id="@+id/rightfragment"
            android:name="com.example.mrchen.custommultiexpanddemo.fragment.ContentFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="end"
            android:layout_weight="1" >
        </fragment>
    </com.example.mrchen.custommultiexpanddemo.ui.PagerEnabledSlidingPaneLayout>

2.侧边栏(主要)

LeftFragment里面只是单纯的数据填充,重点在adapter

/**
 * Created by Mr.chen on 2016/9/30.
 * Description 左边栏
 */
public class LeftFragment extends BaseFragment {
    private ListView lv;
    private List<SideBarItem> list = new ArrayList<SideBarItem>();
    private SideBarAdapter adapter;
    @Override
    public View initView() {
        View view = View.inflate(context, R.layout.fragment_left, null);
        lv = (ListView) view.findViewById(R.id.lv_sidebar);
        return view;
    }

    /**
     * 结构视图(顺序与命名都采用层级式递增)
     *   -1
     *    -11
     *    -12
     *    -13
     */
    @Override
    public void initData() {
        SideBarItem item1 = new SideBarItem("父级1", 1, R.drawable.icon_mark1);
        SideBarItem item2 = new SideBarItem("父级2", 2, R.drawable.icon_mark1);

        SideBarItem item21 = new SideBarItem("子级11", 2.1f, R.drawable.icon_mark1);
        SideBarItem item22 = new SideBarItem("子级12", 2.2f, R.drawable.icon_mark2);
        SideBarItem item23 = new SideBarItem("子级13", 2.3f, R.drawable.icon_mark3);

        SideBarItem item221 = new SideBarItem("子级221", 2.21f, R.drawable.icon_mark1);
        SideBarItem item222 = new SideBarItem("子级222", 2.22f, R.drawable.icon_mark2);
        SideBarItem item223 = new SideBarItem("子级223", 2.23f, R.drawable.icon_mark3);

        item22.setParentItem(item2);
        item23.setParentItem(item2);
        item21.setParentItem(item2);

        item222.setParentItem(item22);
        item223.setParentItem(item22);
        item221.setParentItem(item22);

        list.add(item1);
        list.add(item2);
        list.add(item21);
        list.add(item22);
        list.add(item23);
        list.add(item221);
        list.add(item222);
        list.add(item223);

        adapter = new SideBarAdapter(context, list);
        lv.setAdapter(adapter);
    }

    @Override
    public void setListener() {
        adapter.setSideBarListener(new SideBarAdapter.SideBarListener() {
            @Override
            public void onSideBarItemClick(SideBarItem item, int position) {
                ((MainActivity)context).getContentFragment().setContentText(item);
                Toast.makeText(context,"you click " + item.getItemName(),Toast.LENGTH_SHORT).show();
            }
        });
        super.setListener();
    }

    public void setCurCheckItem(int index){
        adapter.setCurCheckItem(index);
    }
}

这里面的注释写的算比较清楚,而且源码我也放在github

/**
 *侧边栏的适配器
 */


public class SideBarAdapter extends BaseAdapter {

    private List<SideBarItem> list;
    private Context context;
    //左边距
    private int dp8;
    private int dp10;
    //临时储存未展开的item
    private List<SideBarItem> tempList = new LinkedList<>();



    public SideBarAdapter(Context context, List<SideBarItem> list) {
        super();
        this.context = context;
        this.list = list;
        dp8 = DensityUtil.dip2px(context, 8);
        dp10 = DensityUtil.dip2px(context, 10);
        sortItem(list);
        removeUnExpandItem(list);
    }

    /**
     * 对侧边栏的数据进行排序
     * @param list
     */
    private void sortItem(List<SideBarItem> list) {

        Collections.sort(list, new Comparator<SideBarItem>() {

            @Override
            public int compare(SideBarItem lhs, SideBarItem rhs) {
                if (lhs.getOrder() - rhs.getOrder() > 0) {
                    return 1;
                } else if (lhs.getOrder() - rhs.getOrder() < 0) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });

        //设置侧边栏的层级和是否选中
        for (SideBarItem sideBarItem : list) {
            sideBarItem.setLevel(initItemLevel(sideBarItem));
            //因为默认只有一个选中,所以一开始进来,全部的没选中,设为false
            sideBarItem.setCheck(false);
        }

    }

    /**
     * 移除没有展开的item。注意:父亲没有展开,儿子也不给他显示
     * @param list
     */
    private void removeUnExpandItem(List<SideBarItem> list) {
        tempList.clear();
        for (SideBarItem sideBarItem : list) {
            if (sideBarItem.getParentItem() != null) {
                if (!sideBarItem.getParentItem().isExpand()) {
                    sideBarItem.setExpand(false);
                    tempList.add(sideBarItem);
                }
            }
        }
        list.removeAll(tempList);
    }

    // 递归设置level
    private int initItemLevel(SideBarItem item) {
        int level = 1;
        if (item.getParentItem() != null) {
            item.getParentItem().setHasChild(true);
            return (level + initItemLevel(item.getParentItem()));
        }
        return level;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public SideBarItem getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = View.inflate(context, R.layout.adapter_sideritem, null);
            holder = new ViewHolder();
            holder.tv_item = (TextView) convertView.findViewById(R.id.tv_item);
            holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_item);
            holder.iv_arrow = (ImageView) convertView.findViewById(R.id.iv_arrow);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        SideBarItem item = getItem(position);
        //根据level,设置padding来达到递进层级的效果
        if (item.getLevel() == SideBarItem._First) {
            convertView.setPadding(dp10 / 2, dp8, dp8, dp10 / 2);
        } else {
            convertView.setPadding(2 * dp10 * item.getLevel() - dp10, dp8, dp8, dp10 / 2);
        }
        //如果有孩子,就有右边的小箭头,没有的话隐藏的
        if (item.isHasChild()) {
            holder.iv_arrow.setVisibility(View.VISIBLE);
            if (item.isExpand()) {
                holder.iv_arrow.setBackgroundResource(R.mipmap.inspect_bg_right_open);
            }else {
                holder.iv_arrow.setBackgroundResource(R.mipmap.inspect_bg_right_close);
            }
        } else {
            holder.iv_arrow.setVisibility(View.GONE);
        }
        //选中的字体颜色
        if (item.isCheck()) {
            holder.tv_item.setTextColor(0xFF0000FF);
        }else {
            holder.tv_item.setTextColor(0xFF000000);
        }
        holder.iv_icon.setBackgroundResource(item.getResId());
        holder.tv_item.setText(item.getItemName());
        convertView.setTag(R.id.sidebar, item);
        convertView.setTag(R.id.curPosition, position);
        convertView.setOnClickListener(clickListener);
        return convertView;
    }

    OnClickListener clickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            list.addAll(tempList);
            sortItem(list);
            SideBarItem item = (SideBarItem) v.getTag(R.id.sidebar);
            int curPosition = (int) v.getTag(R.id.curPosition);
            item.setCheck(!item.isCheck());
            item.setExpand(!item.isExpand());
            removeUnExpandItem(list);
            //设置回调
            if (listener!=null) {
                listener.onSideBarItemClick(item,curPosition);
            }
            notifyDataSetChanged();
        }
    };

    class ViewHolder {
        TextView tv_item;
        ImageView iv_icon;
        ImageView iv_arrow;
    }

    private SideBarListener listener;

    public void setSideBarListener(SideBarListener listener){
        this.listener = listener;
    }

    public interface SideBarListener{
        void onSideBarItemClick(SideBarItem item, int position);
    }

    /**
     * 设置当前选中的是那个item
     * @param index
     */
    public void setCurCheckItem(int index) {
        list.addAll(tempList);
        sortItem(list);
        SideBarItem item = getItem(index);
        item.setCheck(true);
        item.setExpand(true);
        removeUnExpandItem(list);
        notifyDataSetChanged();
    }

}

最后贴上源码,简单不难
https://github.com/behindeye/CustomMultiExpandDemo.git

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值