RecyclerView 以简单的方式实现层级数列

查阅了很多关于层级数列的,笔者技术薄弱,因为用到了注解和反射什么的,感觉看起来比较复杂,所以想是否可以有别的方式实现,尝试了会儿之后实现了如图的效果在这里插入图片描述
方块为占位的列项,具体图片自行更换

  1. 首先每列都为ImageView + TextView 所以xml文件是这样的list_item.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="40dp" >

    <ImageView
        android:id="@+id/id_item_icon"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:src="@drawable/tree_close" />

    <TextView
        android:layout_centerVertical="true"
        android:id="@+id/id_item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/id_item_icon"
        android:text="@string/hello_world"
        android:textSize="18dp" />

</RelativeLayout>
  1. 因为涉及到层级,感觉用递归的方式去实现会比较简单,所以在设计Javabean时,考虑了树的数据结构的方式
    TreeItem.java
public class TreeItem {

    //储存的数据
    private String mString;
    //层级,方便缩进
    private int level;
    //是否展开
    private boolean open;
    //子项
    private List<TreeItem> mSons;

    public TreeItem(String string) {
        mString = string;
        //每个item默认层级为1,被添加到父类中时根据父类更改层级
        this.level = 1;
        this.open = false;
    }

    public String getString() {
        return mString;
    }

    //是否有子项,若有则返回子项集合,若没有则为空
    public List<TreeItem> getSons() {
        if(mSons == null || mSons.size() == 0)
            return null;
        return mSons;
    }

    public TreeItem addSons(TreeItem sons) {
        //在初次添加时候初始化
        if(mSons == null)
            mSons = new ArrayList<>();
        //根据自己层级为子项设定层级
        sons.setSonLevel(sons,this.level);
        //把子项加入到自己的列表
        mSons.add(sons);
        return this;
    }

    public void setString(String string) {
        mString = string;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }


    public boolean isOpen() {
        return open;
    }

    public void setOpen(boolean open) {
        this.open = open;
    }

    private void setSonLevel(TreeItem treeItem,int level){
        //子项的层级比父类大1
        treeItem.setLevel(level+1);
        //若有子项,则递归调用,设置其层级
        if (treeItem.getSons() != null) {
            for (TreeItem item : treeItem.getSons()) {
                setSonLevel(item, item.getLevel());
            }
        }
    }
}

这样的设计使得添加数据比较方便灵活,结构清晰,可以直接看出显示的效果

mTreeItems.add(new TreeItem("Game")
                .addSons(new TreeItem("Steam")
                        .addSons(new TreeItem("CHi"))
                        .addSons(new TreeItem("Sha")
                                .addSons(new TreeItem("bbbb"))
                                .addSons(new TreeItem("cccc"))))
                .addSons(new TreeItem("LOL"))
                .addSons(new TreeItem("Car")));
  1. TreeListAdapter.java 在适配器中,分为两个列表,一个储存所有的子项,一个用于储存需要展示的数据,在每一次刷新列表时候都重新填充列表
public class TreeListAdapter extends RecyclerView.Adapter<TreeListAdapter.TreeViewHolder> {

    
    private Context mContext;
    //传入的列表数据
    private List<TreeItem> mTreeItems;
    //用于判断是否为第一次加载,方便为展示列表重新添加数据
    private boolean begin;
    //展示的列表数据
    private List<TreeItem> mItemList;

    public TreeListAdapter(Context context, List<TreeItem> treeItems) {
        mContext = context;
        mTreeItems = treeItems;
        mItemList = new ArrayList<>();
        begin = true;
    }


    @NonNull
    @Override
    public TreeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
        TreeViewHolder holder = new TreeViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull TreeViewHolder holder, int position) {
        //在getList方法中为mItemList添加了所有需要展示出来的数据,所以根据顺序依次展示即可
        TreeItem treeItem = mItemList.get(position);
        //设置缩进
        holder.itemView.setPadding(30 * treeItem.getLevel(), 0, 0, 0);

        //如果有子类
        if (treeItem.getSons() != null) {
            //如果子项展开了
            if (treeItem.isOpen()) {
                holder.mImageView.setBackgroundResource(R.drawable.tree_open);
            } else {
                holder.mImageView.setBackgroundResource(R.drawable.tree_close);
            }
            //给有子项的列表图片添加点击事件,更改是否展开
            holder.mImageView.setOnClickListener((v) -> {
                treeItem.setOpen(!treeItem.isOpen());
                //刷新列表,重新添加数据
                begin = true;
                notifyDataSetChanged();
            });
        } else {
            //根节点设置标志
            holder.mImageView.setBackgroundResource(R.drawable.ic_launcher_background);
        }
        //添加文本
        holder.mTextView.setText(treeItem.getString());
    }

    //因为在每次刷新列表首先调用的是这个方法,所以在这个方法中填充mItemList列表
    @Override
    public int getItemCount() {
        if (begin) {
            mItemList.clear();
            getList(mTreeItems);
            //每次刷新只添加一次
            begin = false;
        }
        return mItemList.size();
    }

    //传入TreeItem数列
    private void getList(List<TreeItem> treeItems) {
        //依次取出数列中的每一项
        for (TreeItem treeItem : treeItems) {
            //首先加入到需要展示的列表中
            mItemList.add(treeItem);
            //如果此项又有子项,且是展开的
            if (treeItem.getSons() != null && treeItem.isOpen()) {
                //则把此项的子项列表传入
                getList(treeItem.getSons());
            }
        }
    }
    
    class TreeViewHolder extends RecyclerView.ViewHolder {


        ImageView mImageView;
        TextView mTextView;

        public TreeViewHolder(@NonNull View itemView) {
            super(itemView);
            mImageView = itemView.findViewById(R.id.id_item_icon);
            mTextView = itemView.findViewById(R.id.id_item_text);
        }
    }
}

  1. 主界面xml文件 activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/id_listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>
  1. 主界面activity :MainActivity.java
public class MainActivity extends AppCompatActivity {


    private RecyclerView mRecyclerView;
    private List<TreeItem> mTreeItems = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        addlist();
        TreeListAdapter adapter = new TreeListAdapter(this,mTreeItems);

        mRecyclerView = findViewById(R.id.id_listview);
        mRecyclerView.setAdapter(adapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    }


    private void addlist(){
        mTreeItems.add(new TreeItem("Game")
                .addSons(new TreeItem("Steam")
                        .addSons(new TreeItem("CHi"))
                        .addSons(new TreeItem("Sha")
                                .addSons(new TreeItem("bbbb"))
                                .addSons(new TreeItem("cccc"))))
                .addSons(new TreeItem("LOL"))
                .addSons(new TreeItem("Car")));

    }
}

github地址:https://github.com/jiangkerLove/RecyclerViewList

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值