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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章