需求:实现出多级列表展示效果,每一级可点击,有子级展开子级数据,没有子级响应点击事件
说明:本文说的recyclerview实现多级列表只是效果呈现是多级,实则是平行列表只有一级,当点击节点有子节点,则将子节点数据添加到该节点下边,每个子节点缩进指定距离(如下图)

以下附完整代码
build.gradle文件中引用recyclerview
dependencies {
implementation 'com.android.support:recyclerview-v7:+'
}activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".mainactivity">
<android.support.v7.widget.recyclerview
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</linearlayout>item_multi_level.xml
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<imageview
android:id="@+id/iv_arrow"
android:visibility="gone"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginend="8dp"
/><!--可添加自己所用展开、收起图片-->
<textview
android:id="@+id/tv_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textsize="16sp"
android:textcolor="@android:color/black" />
</linearlayout>treenode.java
package com.example.recycler;
import java.util.arraylist;
import java.util.list;
// treenode.java
public class treenode {
private string id;
private string name;
private int level; // 层级,0开始
private boolean isexpanded; // 是否展开
private treenode parent; // 父节点
private list<treenode> children; // 子节点
private object data; // 其他数据
public treenode(string id, string name,int level) {
this.id = id;
this.name = name;
this.children = new arraylist<>();
this.isexpanded = false;
this.level = level;
}
// getters and setters
public string getid() { return id; }
public void setid(string id) { this.id = id; }
public string getname() { return name; }
public void setname(string name) { this.name = name; }
public int getlevel() { return level; }
public void setlevel(int level) { this.level = level; }
public boolean isexpanded() { return isexpanded; }
public void setexpanded(boolean expanded) { isexpanded = expanded; }
public treenode getparent() { return parent; }
public void setparent(treenode parent) { this.parent = parent; }
public list<treenode> getchildren() { return children; }
public void setchildren(list<treenode> children) { this.children = children; }
public object getdata() { return data; }
public void setdata(object data) { this.data = data; }
// 添加子节点
public void addchild(treenode child) {
child.setparent(this);
child.setlevel(this.level + 1);
children.add(child);
}
// 判断是否有子节点
public boolean haschildren() {
return children != null && !children.isempty();
}
}multileveladapter.java
package com.example.recycler;
import android.support.annotation.nonnull;
import android.support.v7.widget.recyclerview;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.imageview;
import android.widget.textview;
import java.util.arraylist;
import java.util.list;
public class multileveladapter extends recyclerview.adapter<multileveladapter.viewholder> {
private list<treenode> displaynodes; // 实际显示的数据
private list<treenode> allnodes; // 所有数据
private onitemclicklistener listener;
public multileveladapter(list<treenode> data) {
this.allnodes = data;
this.displaynodes = getdisplaynodes(data);
}
// 获取要显示的节点(展开的节点)
private list<treenode> getdisplaynodes(list<treenode> nodes) {
list<treenode> result = new arraylist<>();
for (treenode node : nodes) {
result.add(node);
if (node.isexpanded() && node.haschildren()) {
result.addall(getdisplaynodes(node.getchildren()));
}
}
return result;
}
@nonnull
@override
public viewholder oncreateviewholder(@nonnull viewgroup parent, int viewtype) {
view view = layoutinflater.from(parent.getcontext())
.inflate(r.layout.item_multi_level, parent, false);
return new viewholder(view);
}
@override
public void onbindviewholder(@nonnull final viewholder holder, int position) {
treenode node = displaynodes.get(position);
// 设置缩进
int paddingleft = node.getlevel() * 50; // 每级缩进50dp
system.out.println("缩进:::"+paddingleft);
holder.itemview.setpadding(paddingleft, 0, 0, 0);
// 设置文本
holder.textview.settext(node.getname());
// 设置箭头图标
if (node.haschildren()) {
holder.arrowicon.setvisibility(view.visible);
} else {
holder.arrowicon.setvisibility(view.gone);
}
if (node.isexpanded())
//展开图片设置
holder.arrowicon.setbackground(你的图片)
else
//收起图片设置
holder.arrowicon.setbackground(你的图片)
// 点击事件
holder.itemview.setonclicklistener(new view.onclicklistener() {
@override
public void onclick(view v) {
int adapterposition = holder.getadapterposition();
if (adapterposition != recyclerview.no_position) {
treenode clickednode = displaynodes.get(adapterposition);
if (clickednode.haschildren()) {
// 有子节点:切换展开/收起状态
int removecount = 0;
if (clickednode.isexpanded()) {
removecount = countallchildren(clickednode);
clearallchildexpand(clickednode);
}
clickednode.setexpanded(!clickednode.isexpanded());
refreshdisplaynodes();
//int a = 收起图片
if (clickednode.isexpanded()) {
a = 展开图片
notifyitemrangeinserted(adapterposition + 1, clickednode.getchildren().size());
}else if (!clickednode.isexpanded()&&removecount!=0){
notifyitemrangeremoved(adapterposition + 1, removecount);
}
holder.arrowicon.setbackground(a)
} else {
// 没有子节点:触发点击事件
if (listener != null) {
listener.onitemclick(clickednode);
}
}
}
}
});
// 长按事件(可选)
holder.itemview.setonlongclicklistener(new view.onlongclicklistener() {
@override
public boolean onlongclick(view v) {
if (listener != null) {
return listener.onitemlongclick(displaynodes.get(holder.getadapterposition()));
}
return false;
}
});
}
// 计算节点的所有子节点数量(包括子节点的子节点)
private int countallchildren(treenode node) {
int count = 0;
if (node.haschildren() && node.isexpanded()) {
for (treenode child : node.getchildren()) {
count++;
if (child.isexpanded()) {
count += countallchildren(child);
}
}
}
return count;
}
private void clearallchildexpand(treenode node) {
if (node.haschildren()) {
for (treenode child : node.getchildren()) {
child.setexpanded(false);
clearallchildexpand(child);
}
}
}
// 刷新显示的数据
private void refreshdisplaynodes() {
displaynodes = getdisplaynodes(allnodes);
}
@override
public int getitemcount() {
return displaynodes.size();
}
// 设置数据
public void setdata(list<treenode> data) {
this.allnodes = data;
refreshdisplaynodes();
notifydatasetchanged();
}
// 展开/收起所有节点
public void expandall() {
setexpandedforall(allnodes, true);
refreshdisplaynodes();
notifydatasetchanged();
}
public void collapseall() {
setexpandedforall(allnodes, false);
refreshdisplaynodes();
notifydatasetchanged();
}
private void setexpandedforall(list<treenode> nodes, boolean expanded) {
for (treenode node : nodes) {
node.setexpanded(expanded);
if (node.haschildren()) {
setexpandedforall(node.getchildren(), expanded);
}
}
}
// viewholder
static class viewholder extends recyclerview.viewholder {
textview textview;
imageview arrowicon;
public viewholder(@nonnull view itemview) {
super(itemview);
textview = itemview.findviewbyid(r.id.tv_item_name);
arrowicon = itemview.findviewbyid(r.id.iv_arrow);
}
}
// 点击监听接口
public interface onitemclicklistener {
void onitemclick(treenode node);
boolean onitemlongclick(treenode node);
}
public void setonitemclicklistener(onitemclicklistener listener) {
this.listener = listener;
}
}mainactivity.java
package com.example.recycler;
import android.app.activity;
import android.os.bundle;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.util.log;
import android.widget.toast;
import java.util.arraylist;
import java.util.list;
// mainactivity.java
public class mainactivity extends activity {
private recyclerview recyclerview;
private multileveladapter adapter;
@override
protected void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
recyclerview = findviewbyid(r.id.recyclerview);
recyclerview.setlayoutmanager(new linearlayoutmanager(this));
// 创建测试数据
list<treenode> data = createtestdata();
adapter = new multileveladapter(data);
recyclerview.setadapter(adapter);
// 设置点击监听
adapter.setonitemclicklistener(new multileveladapter.onitemclicklistener() {
@override
public void onitemclick(treenode node) {
// 处理没有子节点的点击事件
toast.maketext(mainactivity.this,
"点击了: " + node.getname(), toast.length_short).show();
// 可以在这里处理业务逻辑
handleleafclick(node);
}
@override
public boolean onitemlongclick(treenode node) {
// 长按事件
showoptionsdialog(node);
return true;
}
});
}
// 创建测试数据(支持无限层级)
private list<treenode> createtestdata() {
list<treenode> rootnodes = new arraylist<>();
// 第1级
for (int i = 1; i <= 3; i++) {
treenode level1 = new treenode("1-" + i, "一级节点 " + i,0);
level1.setlevel(0);
// 第2级
for (int j = 1; j <= 2; j++) {
treenode level2 = new treenode("2-" + i + "-" + j, "二级节点 " + i + "-" + j,level1.getlevel());
level1.addchild(level2);
// 第3级
for (int k = 1; k <= (i == 1 ? 3 : 0); k++) {
treenode level3 = new treenode("3-" + i + "-" + j + "-" + k,
"三级节点 " + i + "-" + j + "-" + k,level2.getlevel());
level2.addchild(level3);
// 第4级(演示无限层级)
if (i == 1 && j == 1) {
for (int l = 1; l <= 2; l++) {
treenode level4 = new treenode("4-" + i + "-" + j + "-" + k + "-" + l,
"四级节点 " + i + "-" + j + "-" + k + "-" + l,level3.getlevel());
level3.addchild(level4);
}
}
}
}
rootnodes.add(level1);
}
return rootnodes;
}
// 处理叶子节点点击
private void handleleafclick(treenode node) {
// 这里实现你的业务逻辑
log.d("multilevel", "点击了叶子节点: " + node.getname());
}
}到此这篇关于android中recyclerview实现多级列表展示效果的文章就介绍到这了,更多相关android recyclerview多级列表内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论