Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V4 树形结构Adapter封装 #3769

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
android:name=".activity.dragswipe.DefaultDragAndSwipeActivity"
android:exported="false" />
<activity android:name=".activity.scene.GroupDemoActivity" />
<activity android:name=".activity.treenode.TreeNodeActivity" />
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.chad.baserecyclerviewadapterhelper.activity.itemclick.ItemClickActivi
import com.chad.baserecyclerviewadapterhelper.activity.loadmore.AutoLoadMoreRefreshUseActivity
import com.chad.baserecyclerviewadapterhelper.activity.loadmore.NoAutoAutoLoadMoreRefreshUseActivity
import com.chad.baserecyclerviewadapterhelper.activity.scene.GroupDemoActivity
import com.chad.baserecyclerviewadapterhelper.activity.treenode.TreeNodeActivity
import com.chad.baserecyclerviewadapterhelper.activity.upfetch.UpFetchUseActivity
import com.chad.baserecyclerviewadapterhelper.databinding.ActivityHomeBinding
import com.chad.baserecyclerviewadapterhelper.entity.HomeEntity
Expand Down Expand Up @@ -80,5 +81,6 @@ class HomeActivity : AppCompatActivity() {

HomeEntity(sectionTitle = "场景演示"),
HomeEntity("Group(ConcatAdapter)", GroupDemoActivity::class.java, R.mipmap.gv_animation),
HomeEntity("Tree Node", TreeNodeActivity::class.java, R.mipmap.gv_expandable),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package com.chad.baserecyclerviewadapterhelper.activity.treenode

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.chad.baserecyclerviewadapterhelper.activity.home.adapter.HomeTopHeaderAdapter
import com.chad.baserecyclerviewadapterhelper.activity.treenode.adapter.TreeNodeAdapter
import com.chad.baserecyclerviewadapterhelper.base.BaseViewBindingActivity
import com.chad.baserecyclerviewadapterhelper.databinding.ActivityUniversalRecyclerBinding
import com.chad.baserecyclerviewadapterhelper.entity.MyNodeEntity
import com.chad.baserecyclerviewadapterhelper.entity.MyNodeLoadingEntity
import com.chad.library.adapter.base.BaseNode
import com.chad.library.adapter.base.QuickAdapterHelper
import com.chad.library.adapter.base.dragswipe.QuickDragAndSwipe

/**
* 树形结构演示Adapter
*
* @author Dboy233
*/
class TreeNodeActivity : BaseViewBindingActivity<ActivityUniversalRecyclerBinding>() {

// val TAG by lazy { localClassName }

private lateinit var helper: QuickAdapterHelper

val mAdapter = TreeNodeAdapter()

val loadingNode = MyNodeLoadingEntity()

private val quickDragAndSwipe = QuickDragAndSwipe()
.setSwipeMoveFlags(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT)

override fun initBinding(): ActivityUniversalRecyclerBinding {
return ActivityUniversalRecyclerBinding.inflate(
layoutInflater
)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding.titleBar.title = "Tree Node"
viewBinding.titleBar.setOnBackListener { v: View? -> finish() }

helper = QuickAdapterHelper.Builder(mAdapter)
.build()
.addBeforeAdapter(HomeTopHeaderAdapter())

viewBinding.rv.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

viewBinding.rv.adapter = helper.adapter

mAdapter.setOnItemClickListener { adapter, view, position ->
val item = mAdapter.getItem(position)
if (item?.childNodes != null && item.childNodes!!.isEmpty()) {
addLoadingNode(item)
}
//一层层展开
mAdapter.switchState(position, 1)
//全部子节点展开
//mAdapter.switchState(position)
}

mAdapter.setOnItemLongClickListener { adapter, view, position ->
val item = mAdapter.getItem(position) ?: return@setOnItemLongClickListener false
mAdapter.addNode(item.parentNode!!, getChildNode(item), getChildNodeIndex(item), 1)
true
}

quickDragAndSwipe.attachToRecyclerView(viewBinding.rv)
.setDataCallback(mAdapter)

mAdapter.addNodes(getList(), 0)

Toast.makeText(this, "长按添加Item,Long press to add Item", Toast.LENGTH_SHORT).show()
}

/**
* 添加更多节点
*/
private fun addLoadingNode(parentNode: BaseNode) {
///添加loading节点
mAdapter.addNode(parentNode, loadingNode)
///模拟异步操作
viewBinding.root.postDelayed({
///移除Loading节点
mAdapter.remove(loadingNode)
///添加新的节点
mAdapter.addNodes(parentNode,moreNode())
}, 2000)
}

///获取更多节点
private fun moreNode(): List<BaseNode> {
return mutableListOf(
MyNodeEntity("new node"),
MyNodeEntity("load more node", mutableListOf()),
MyNodeEntity("new node")
)
}


private fun getChildNodeIndex(item: BaseNode): Int {
return mAdapter.getChildNodeIndex(item) + 1
}

private fun getChildNode(item: BaseNode): BaseNode {
return when (item.nodeType) {
TreeNodeAdapter.TYPE_FILE -> {
MyNodeEntity(
"new file node"
)
}

else -> {
MyNodeEntity(
"new folder node",
mutableListOf(
MyNodeEntity(
"new new folder", mutableListOf(
MyNodeEntity(
"new file node"
)
)
)
)
)
}
}
}

/**
* 所有节点用同一个实体类
*/
private fun getList(): List<MyNodeEntity> {
return listOf(
MyNodeEntity(
"My Folders", mutableListOf(
MyNodeEntity(
"My Pictures folder", mutableListOf(
MyNodeEntity("Belle.png"),
MyNodeEntity("Handsome_guy.png"),
MyNodeEntity(
"Private picture folders", mutableListOf(
MyNodeEntity("凤姐.png")
)
)
)
),
MyNodeEntity(
"Work Folders", mutableListOf(
MyNodeEntity("life_summary.txt")
)
)
)
),
MyNodeEntity(
"Her folder", mutableListOf(
MyNodeEntity(
"Her picture folder", mutableListOf(
MyNodeEntity(
"Private picture folders", mutableListOf(
MyNodeEntity("Swimsuit.png")
)
),
MyNodeEntity("Mountaintop.png"),
MyNodeEntity("Park.png"),
)
),
MyNodeEntity(
"Her working folder", mutableListOf(
MyNodeEntity("how_to_work_easily.txt")
)
)
)
),
MyNodeEntity("load more node", mutableListOf())
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.chad.baserecyclerviewadapterhelper.activity.treenode.adapter;

import android.content.Context;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.chad.baserecyclerviewadapterhelper.R;
import com.chad.baserecyclerviewadapterhelper.entity.MyNodeEntity;
import com.chad.library.adapter.base.BaseNode;
import com.chad.library.adapter.base.BaseTreeNodeAdapter;
import com.chad.library.adapter.base.dragswipe.listener.DragAndSwipeDataCallback;
import com.chad.library.adapter.base.viewholder.QuickViewHolder;

/**
* @author Dboy233
*/
public class TreeNodeAdapter extends BaseTreeNodeAdapter implements DragAndSwipeDataCallback {

public final static int TYPE_FOLDER = 1;

public final static int TYPE_FILE = 2;

public final static int TYPE_LOAD_MORE = 3;


public TreeNodeAdapter() {
addItemType(TYPE_FILE, new OnMultiItemAdapterListener<BaseNode, QuickViewHolder>() {
@NonNull
@Override
public QuickViewHolder onCreate(@NonNull Context context, @NonNull ViewGroup parent,
int viewType) {
return new QuickViewHolder(R.layout.item_file, parent);
}

@Override
public void onBind(@NonNull QuickViewHolder holder, int position,
@Nullable BaseNode item) {
if (item instanceof MyNodeEntity) {
holder.setText(R.id.tv, ((MyNodeEntity) item).getName())
.setText(R.id.sub_tv, ((MyNodeEntity) item).getTime().toString());
}
}
}).addItemType(TYPE_FOLDER, new OnMultiItemAdapterListener<BaseNode, QuickViewHolder>() {
@NonNull
@Override
public QuickViewHolder onCreate(@NonNull Context context, @NonNull ViewGroup parent,
int viewType) {
return new QuickViewHolder(R.layout.item_folder, parent);
}

@Override
public void onBind(@NonNull QuickViewHolder holder, int position,
@Nullable BaseNode item) {
if (item==null) {
return;
}
if (item instanceof MyNodeEntity) {
holder.setText(R.id.tv, ((MyNodeEntity) item).getName());
}

int angle = item.isExpand() ? 0 : -90;
holder.getView(R.id.iv).setRotation(angle);

int nodeDeep = getNodeDepth(item);
switch (nodeDeep) {
case 2 -> holder.setImageResource(R.id.iv_head, R.mipmap.head_img1);
case 3 -> holder.setImageResource(R.id.iv_head, R.mipmap.head_img2);
default -> holder.setImageResource(R.id.iv_head, R.mipmap.head_img0);
}
}
});

//加载更多
addItemType(TYPE_LOAD_MORE, new OnMultiItemAdapterListener<BaseNode, QuickViewHolder>() {
@Override
public void onBind(@NonNull QuickViewHolder holder, int position,
@Nullable BaseNode item) {
}
@NonNull
@Override
public QuickViewHolder onCreate(@NonNull Context context, @NonNull ViewGroup parent,
int viewType) {
return new QuickViewHolder(R.layout.view_load_more,parent);
}
});
}

@Override
public void dataSwap(int fromPosition, int toPosition) {
swap(fromPosition, toPosition);
}

@Override
public void dataRemoveAt(int position) {
removeAt(position);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.chad.baserecyclerviewadapterhelper.entity;

import androidx.annotation.Nullable;

import com.chad.baserecyclerviewadapterhelper.activity.treenode.adapter.TreeNodeAdapter;
import com.chad.library.adapter.base.BaseNode;

import java.util.Date;
import java.util.List;

/**
* @author Dboy233
*/
public class FileNodeEntity extends BaseNode {

private String name;

private Date time = new Date();

public FileNodeEntity(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Date getTime() {
return time;
}

public void setTime(Date time) {
this.time = time;
}

@Override
public int getNodeType() {
return TreeNodeAdapter.TYPE_FILE;
}

@Nullable
@Override
public List<BaseNode> getChildNodes() {
return null;
}
}
Loading