Android 自定义二维列表

一个超简单的二维嵌套列表

直接上代码:

Adapter代码:

package com.example.SecondProject.Adapter;

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

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

import com.example.SecondProject.Base.MainApplication;
import com.example.SecondProject.R;
import com.example.SecondProject.databinding.FatherListItemBinding;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 二维列表
public class NestedListAdapter extends RecyclerView.Adapter<NestedListAdapter.NestedListViewHolder> {

    private final String TAG = "NestedListAdapter";
// 常量 ----------------------------
    public static final String TITLE = "title";  // string
    public static final String DATA = "data";  // List<String>
    public static final String EXPAND = "expand";  // boolean

    Context my_context;
    FatherListItemBinding viewBinding;
    List<Map<String,Object>> lists = new ArrayList<>();  // 主数据

    public NestedListAdapter(Context context, @NonNull List<Map<String,Object>> lists, @Nullable onItemClickListener onItemClickListener){
        my_context = context;
        this.lists = lists;
        this.onItemClickListener = onItemClickListener;
    }

    @NonNull
    @Override
    public NestedListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        viewBinding = FatherListItemBinding.inflate(LayoutInflater.from(my_context));
        NestedListAdapter.NestedListViewHolder holder = new NestedListAdapter.NestedListViewHolder(viewBinding);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull NestedListViewHolder holder, int position) {
        Map<String,Object> list_data = lists.get(position);
        String title = (String) list_data.get(TITLE);
        holder.viewBinding.fatherTitle.setText(title);
        List<String> son_data = (List<String>) list_data.get(DATA);
        if(son_data!=null){
            RecyclerView son = new RecyclerView(my_context);
            ItemListAdapter son_adapter = new ItemListAdapter(my_context,son_data,position);
            son.setAdapter(son_adapter);
            son.setLayoutManager(new LinearLayoutManager(my_context, LinearLayoutManager.VERTICAL, false));
            holder.viewBinding.sonView.addView(son);
//            holder.viewBinding.sonView.setVisibility(View.VISIBLE);
            holder.viewBinding.fatherView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(holder.viewBinding.sonView.getVisibility()==View.GONE){
                        holder.viewBinding.arrow.setImageResource(R.mipmap.arrow_down_icon);
                        holder.viewBinding.sonView.setVisibility(View.VISIBLE);
                    }else {
                        holder.viewBinding.arrow.setImageResource(R.mipmap.arrow_right_icon);
                        holder.viewBinding.sonView.setVisibility(View.GONE);
                    }
                }
            });
            // 是否展开
            Boolean expandValue = (Boolean) list_data.get(EXPAND);
            boolean isExpand = expandValue != null && expandValue;
            if (isExpand) {
                holder.viewBinding.arrow.setImageResource(R.mipmap.arrow_down_icon);
                holder.viewBinding.sonView.setVisibility(View.VISIBLE);
            } else {
                holder.viewBinding.arrow.setImageResource(R.mipmap.arrow_right_icon);
                holder.viewBinding.sonView.setVisibility(View.GONE);
            }
        }else {
            holder.viewBinding.arrow.setVisibility(View.GONE);
            holder.viewBinding.sonView.setVisibility(View.GONE);
            holder.viewBinding.fatherView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    MainApplication.getInstance().showToast("暂无数据",0);
                }
            });
        }

    }

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

    public class NestedListViewHolder extends RecyclerView.ViewHolder{
        FatherListItemBinding viewBinding;
        public NestedListViewHolder(FatherListItemBinding viewBinding) {
            super(viewBinding.getRoot());
            this.viewBinding = viewBinding;
        }
    }

    // 修改整个列表数据
    public void upDateList(List<Map<String,Object>> lists){
        this.lists = lists;
        notifyDataSetChanged();
    }

    // 修改单个列表数据
    public void updateItemInChildList(int parentPosition, int childPosition, String newData) {
        if (parentPosition >= 0 && parentPosition < lists.size()) {
            Map<String, Object> parentItem = lists.get(parentPosition);
            List<String> childData = (List<String>) parentItem.get(DATA);
            if (childData != null && childPosition >= 0 && childPosition < childData.size()) {
                // 修改指定子项的数据
                childData.set(childPosition, newData);
                notifyItemChanged(parentPosition);
            }
        }
    }



// 接口 ----------------------------------------------------------
    public interface onItemClickListener<T>{
        void onItemClickListener(T list_position,int item_position);
    }
    public onItemClickListener onItemClickListener;
    public void setOnItemClickListener(onItemClickListener onItemClickListener){
        this.onItemClickListener = onItemClickListener;
    }


// 子列表 adapter ----------------------------------------------------------
    private class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ItemListViewHolder>{

        public List<String> items;
        public int id = 0;  // 当前的列表索引

        public ItemListAdapter(Context context, List<String> items, int id){
            my_context = context;
            this.items = items;
            this.id = id;
        }

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

        @Override
        public void onBindViewHolder(@NonNull ItemListViewHolder holder, int position) {
            String name = items.get(position);
            holder.item_name.setText(name);
            holder.item_name.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(onItemClickListener != null){
                        onItemClickListener.onItemClickListener(id,position);
                    }
                }
            });
        }

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

        public class ItemListViewHolder extends RecyclerView.ViewHolder{
            private TextView item_name;
            public ItemListViewHolder(View itemView) {
                super(itemView);
                item_name = itemView.findViewById(R.id.item_name);
            }
        }
    }

}

父列表布局文件:R.layout.father_list_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/gray_2"/>
    
    <RelativeLayout
        android:id="@+id/father_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:orientation="horizontal"
        android:background="?attr/selectableItemBackground">

        <TextView
            android:id="@+id/father_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_alignParentLeft="true"
            android:text="标题"
            android:textSize="15sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:gravity="center"/>

        <ImageView
            android:id="@+id/arrow"
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="20dp"
            android:src="@mipmap/arrow_right_icon" />
        
        
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/son_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:visibility="gone"/>
    
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/gray_2"/>

</LinearLayout>

子列表布局文件:R.layout.son_list_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <View
        android:layout_width="match_parent"
        android:layout_height="0.8dp"
        android:background="@color/gray_2"/>
    <TextView
        android:id="@+id/item_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="8dp"
        android:paddingBottom="8dp"
        android:text="设为私密"
        android:textSize="15sp"
        android:textColor="@color/black"
        android:gravity="center"
        android:background="?attr/selectableItemBackground"
        android:clickable="true"
        android:focusable="true"/>

</LinearLayout>

使用方法:

List<Map<String,Object>> lists = new ArrayList<>();
Map<String,Object> list_1 = new HashMap<>();
list_1.put(NestedListAdapter.TITLE,"标题一");
List<String> item_1 = new ArrayList<>();
item_1.add("111");
item_1.add("222");
item_1.add("333");
list_1.put(NestedListAdapter.DATA,item_1);
lists.add(list_1);

Map<String,Object> list_2 = new HashMap<>();
list_2.put(NestedListAdapter.TITLE,"标题二");
List<String> item_2 = new ArrayList<>();
item_2.add("嘿嘿嘿");
item_2.add("哈哈哈");
list_2.put(NestedListAdapter.DATA,item_2);
list_2.put(NestedListAdapter.EXPAND,true);
lists.add(list_2);

Map<String,Object> list_3 = new HashMap<>();
list_3.put(NestedListAdapter.TITLE,"标题三");
lists.add(list_3);

NestedListAdapter adapter = new NestedListAdapter(this, lists, new NestedListAdapter.onItemClickListener() {
    @Override
    public void onItemClickListener(Object list_position,int item_position) {
        loge("点击了列表项数:"+list_position + " / 子项数:"+item_position);
    }
});
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));

总体思路:

思路非常简单:在父列表布局中定义一个用于存放子列表的 LinearLayout 当父列表子项数据中具有子列表时则显示并动态添加一个 RecyclerView ,如果没有则隐藏。
父列表子项数据定义用的是 HashMap ,title 键存放 string 类型的列表标题、data 键存放 List<String> 类型的子列表标题、expand 键存放 boolean 类型的列表展开/收缩标识
其余根据需求自行修改即可

猜你喜欢

转载自blog.csdn.net/lxt1292352578/article/details/132667825
今日推荐