一个超简单的二维嵌套列表
直接上代码:
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 类型的列表展开/收缩标识
其余根据需求自行修改即可