RecyclerView 分层级展示(抽屉) TreeView

先看效果

难点:  数据层级的划分;理清楚层级关系, 剩下的就简单明了了;

1. 第一步 new Adapter, and setAdapter; (不需要setLayoutManager, Adapter里有set);

mAdapter = new TreeViewAdapter(getContext(),mRecyclerView);
mRecyclerView.setAdapter(mAdapter);

2. 第二步, 划分数据层级;(不好说, 自己看代码理解)

注意点: CommonMenu的构造方法中初始化层级, 是否展开;

CommonMenu 就是菜单, 菜单中也可能包含菜单, 具体是包含还是并列同级, 取决于Level_等级;

0~3都是菜单, LEVEL_ITEM 为具体对象;

Set数据过程 以及需要的实体类 如下:(具体对象的实体类就贴了一个KaKou, 其他的类似, 继承BaseMenu即可)

            //初始化 Adapter需要的数据mBaseList 
            List mBaseList = new ArrayList<>();

            for (int i = 0; i < 2; i++) {
                CommonMenu lcMenu = new CommonMenu(BaseMenu.LEVEL_1, false);
                lcMenu.setName("林场" + i);

                List lcChildList = new ArrayList<>();
                lcMenu.setChild(lcChildList);

                CommonMenu yunTaiMenu = new CommonMenu(BaseMenu.LEVEL_2, false);
                yunTaiMenu.setName("云台");
                lcChildList.add(yunTaiMenu);

                List ytChildList = new ArrayList<>();
                for (int j = 0; j < 2; j++) {
                    YunTai item = new YunTai();
                    item.setName("云台Name" + j);
                    ytChildList.add(item);
                }
                yunTaiMenu.setChild(ytChildList);

                CommonMenu kkMenu = new CommonMenu(BaseMenu.LEVEL_2, false);
                kkMenu.setName("卡口");
                lcChildList.add(kkMenu);

                List kkChildList = new ArrayList<>();
                for (int j = 0; j < 2; j++) {
                    KaKou item = new KaKou();
                    item.setName("卡口Name" + j);
                    kkChildList.add(item);
                }
                kkMenu.setChild(kkChildList);

                CommonMenu fdMenu = new CommonMenu(BaseMenu.LEVEL_2, false);
                fdMenu.setName("防盗");
                lcChildList.add(fdMenu);

                List fdChildList = new ArrayList<>();
                for (int j = 0; j < 2; j++) {
                    FangDao item = new FangDao();
                    item.setName("防盗Name" + j);
                    fdChildList.add(item);
                }
                fdMenu.setChild(fdChildList);

                CommonMenu qxzMenu = new CommonMenu(BaseMenu.LEVEL_2, false);
                qxzMenu.setName("气象站");
                lcChildList.add(qxzMenu);

                List qxzChildList = new ArrayList<>();
                for (int j = 0; j < 2; j++) {
                    QiXiangZhan item = new QiXiangZhan();
                    item.setName("气象站Name" + j);
                    qxzChildList.add(item);
                }
                qxzMenu.setChild(qxzChildList);


                mBaseList.add(lcMenu);
            }

            mAdapter.setBaseList(mBaseList);
            mAdapter.notifyDataSetChanged();

public abstract class BaseMenu {

    public static final int LEVEL_0 = 0;//林局
    public static final int LEVEL_1 = 1;//林场
    public static final int LEVEL_2 = 2;//云台
    public static final int LEVEL_3 = 3;//备用-管护站
    public static final int LEVEL_ITEM = 4;//具体设备

    protected String name;
    protected int level = LEVEL_ITEM;
    protected boolean expand = true;

    public boolean isExpand() {
        return expand;
    }

    public void setExpand(boolean expand) {
        this.expand = expand;
    }

    public int getLevel() {
        return level;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isItem(){
        return level == LEVEL_ITEM;
    }

    public abstract List getChild();

}
public class CommonMenu extends BaseMenu {

    private List child;

    public List getChild() {
        return child;
    }

    public void setChild(List child) {
        this.child = child;
    }

    public CommonMenu(int level, boolean expand) {
        this.level = level;
        this.expand = expand;
    }
}
public class KaKou extends BaseMenu{

    private String uuid;
    private String name;
    private String lon;
    private String lat;

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public List getChild() {
        return null;
    }

    public String getLon() {
        return lon;
    }

    public void setLon(String lon) {
        this.lon = lon;
    }

    public String getLat() {
        return lat;
    }

    public void setLat(String lat) {
        this.lat = lat;
    }
}

3. 第三步 愉快的复制粘贴过程(Adapter, 以及 布局)


import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.sxwy.fanghuo.R;
import com.sxwy.fanghuo.data.BaseMenu;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/**
 * Created by ZhouWengong on 2023/5/17.
 */
public class TreeViewAdapter extends RecyclerView.Adapter {
    public static final String TAG = TreeViewAdapter.class.getSimpleName();
    private LinearLayoutManager layoutManager;

    private final List mCurrentList;//当前展示的数据
    private Context mContext;

    private RecyclerView mRecyclerView;

    public TreeViewAdapter(Context context, RecyclerView recyclerView) {
        mContext = context;
        mCurrentList = new ArrayList<>();
        if (recyclerView != null) {
            mRecyclerView = recyclerView;
            layoutManager = new LinearLayoutManager(context);
            mRecyclerView.setLayoutManager(layoutManager);

            //展开与关闭时的动画耗时;
            RecyclerView.ItemAnimator itemAnimator = recyclerView.getItemAnimator();
            if (itemAnimator != null) {
                int duration = 10;
                itemAnimator.setAddDuration(duration);
                itemAnimator.setRemoveDuration(duration);
            }
        }
    }

    public void setBaseList(List baseList) {
        if (baseList != null) {
            initCurrentMenu(baseList);
        }
    }

    private void initCurrentMenu(List baseMenus) {
        for (BaseMenu baseMenu : baseMenus) {
            mCurrentList.add(baseMenu);
            if (!baseMenu.isItem()) {
                if (baseMenu.getChild() != null && baseMenu.isExpand()) {
                    initCurrentMenu(baseMenu.getChild());
                }
            }
        }
    }

    private void onMenuExpand(BaseMenu baseMenu, int position) {
        if (baseMenu.getChild() != null) {
            int size = mCurrentList.size();

            if (baseMenu.isExpand()) {
                int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition();

                insertMenuChild(baseMenu, position + 1);

                int itemCount = mCurrentList.size() - size;
                notifyItemRangeInserted(position + 1, itemCount);
                notifyItemRangeChanged(position, mCurrentList.size());

                int toPosition = position + itemCount;


                if (lastVisibleItemPosition < toPosition) {
                    mRecyclerView.scrollToPosition(toPosition);
                }
            } else {
                removeMenuChild(baseMenu);
                notifyItemRangeRemoved(position + 1, size - mCurrentList.size());
                notifyItemRangeChanged(position, mCurrentList.size());
            }
        } else {
            notifyItemChanged(position);
        }
    }

    private void insertMenuChild(BaseMenu menu, int position) {
        if (menu.isExpand()) {
            List child = menu.getChild();
            if (child != null) {
//                for (BaseMenu baseMenu : child) {//child逆序添加,因为position固定;
//                    mCurrentList.add(position , baseMenu);
//                    if (!baseMenu.isItem() && baseMenu.isExpand()) {
//                        insertMenuChild(baseMenu, position + 1);
//                    }
//                }
                for (int i = child.size() - 1; i >= 0; i--) {//逆序遍历, 正序添加
                    BaseMenu baseMenu = child.get(i);
                    mCurrentList.add(position, baseMenu);
                    if (!baseMenu.isItem() && baseMenu.isExpand()) {
                        insertMenuChild(baseMenu, position + 1);
                    }
                }

            }
        }
    }

    private void removeMenuChild(BaseMenu menu) {
        List child = menu.getChild();
        if (child != null) {
            mCurrentList.removeAll(child);
            for (BaseMenu baseMenu : child) {
                removeMenuChild(baseMenu);
            }
        }
    }


    public int getLayoutId(int viewType) {
        int ret = 0;
        switch (viewType) {
            case BaseMenu.LEVEL_0:
                break;
            case BaseMenu.LEVEL_1:
                ret = R.layout.item_treeview_menu_1;
                break;
            case BaseMenu.LEVEL_2:
                ret = R.layout.item_treeview_menu_2;
                break;
            case BaseMenu.LEVEL_3:
                break;
            case BaseMenu.LEVEL_ITEM:
                ret = R.layout.item_treeview_menu_item;
                break;
        }

        return ret;
    }

    @Override
    public int getItemViewType(int position) {
        return mCurrentList.get(position).getLevel();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return ViewHolder.getViewHolder(mContext, parent, getLayoutId(viewType));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        BaseMenu baseMenu = mCurrentList.get(position);
        ((TextView) holder.getView(R.id.text)).setText(baseMenu.getName());
        if (!baseMenu.isItem()) {//我的图片资源箭头是朝右的,根据实际情况修改即可
            holder.getView(R.id.indicator).setRotation(baseMenu.isExpand() ? 90 : 270);
        }
        View holderView = holder.getView(R.id.parent);
        holderView.setTag(position);
        holderView.setOnClickListener(onClickListener);

    }

    private final View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = (int) v.getTag();
            BaseMenu baseMenu = mCurrentList.get(position);
            if (!baseMenu.isItem()) {
                baseMenu.setExpand(!baseMenu.isExpand());
                onMenuExpand(baseMenu, position);
            }else {
                //todo item点击时触发
            }
        }
    };

    @Override
    public int getItemCount() {
        return mCurrentList.size();
    }

}

布局只传了一个, 根据情况复制粘贴就可以,

注意: 每个Level 对应一个布局, 每个布局的paddingStart应该设置合理的间距(@dimen/treeViewMarginLevel_1)

item_treeview_menu_1.xml




    

        


        


        
    

    


你可能感兴趣的:(android,java,开发语言)