在app
的build.gradle
在添加以下代码
1、implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
,这个里面带的适配器,直接调用就即可
这依赖包还需要得到要添加,在Project
的build.gradle
在添加以下代码,不添加就不行
allprojects {
repositories {
...
maven { url "https://jitpack.io" }//加上
}
}
NodeTreeAdapter.kt
package com.example.myapplication3.adapter.node.tree
import com.chad.library.adapter.base.BaseNodeAdapter
import com.chad.library.adapter.base.entity.node.BaseNode
import com.chad.library.adapter.base.module.DraggableModule
import com.example.myapplication3.adapter.node.tree.provider.FirstProvider
import com.example.myapplication3.adapter.node.tree.provider.SecondProvider
import com.example.myapplication3.adapter.node.tree.provider.ThirdProvider
import com.example.myapplication3.entity.node.tree.FirstNode
import com.example.myapplication3.entity.node.tree.SecondNode
import com.example.myapplication3.entity.node.tree.ThirdNode
class NodeTreeAdapter : BaseNodeAdapter()
{
init {
addFullSpanNodeProvider(FirstProvider())
addFullSpanNodeProvider(SecondProvider())
addNodeProvider(ThirdProvider())
}
override fun getItemType(data: List<BaseNode>, position: Int): Int {
val node = data[position]
if (node is FirstNode) {
return 1
} else if (node is SecondNode) {
return 2
} else if (node is ThirdNode) {
return 3
}
return -1
}
val EXPAND_COLLAPSE_PAYLOAD = 110
}
第一个级节点提供类FirstProvider.kt
package com.example.myapplication3.adapter.node.tree.provider
import android.view.View
import android.widget.ImageView
import com.chad.library.adapter.base.entity.node.BaseNode
import com.chad.library.adapter.base.module.DraggableModule
import com.chad.library.adapter.base.provider.BaseNodeProvider
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.adapter.node.tree.NodeTreeAdapter
import com.example.myapplication3.entity.node.tree.FirstNode
import com.example.myapplication3.ext.rotation
class FirstProvider : BaseNodeProvider(){
override val itemViewType: Int
get() = 1
override val layoutId: Int
get() = R.layout.item_node_first
override fun convert(helper: BaseViewHolder, data: BaseNode) {
val entity: FirstNode = data as FirstNode
helper.setText(R.id.header, entity.title)
// 增量刷新,使用动画变化箭头
setArrowSpin(helper, data, false)
}
override fun convert(helper: BaseViewHolder, data: BaseNode, payloads: List<Any>) {
for (payload in payloads) {
if (payload is Int && payload == NodeTreeAdapter().EXPAND_COLLAPSE_PAYLOAD) {
// 增量刷新,使用动画变化箭头
setArrowSpin(helper, data, true)
}
}
}
override fun onClick(helper: BaseViewHolder, view: View, data: BaseNode, position: Int) {
getAdapter()!!.expandOrCollapse(position,true,true,NodeTreeAdapter().EXPAND_COLLAPSE_PAYLOAD)
}
// override fun onLongClick(helper: BaseViewHolder, view: View, data: BaseNode, position: Int): Boolean {
// val entity: FirstNode = data as FirstNode
// if (entity.isExpanded) {
// view.postDelayed(Runnable {
// getAdapter()!!.collapse(position)
// },300)
// }
else {
getAdapter()!!.expandAndCollapseOther(position)
}
// return true //只执行长按事件
return false
// }
private fun setArrowSpin(helper: BaseViewHolder, data: BaseNode, isAnimate: Boolean) {
val entity: FirstNode = data as FirstNode
val imageView = helper.getView<ImageView>(R.id.ivIcon)
if (entity.isExpanded) {
imageView.rotation(90f, isAnimate)
} else {
imageView.rotation(0f, isAnimate)
}
}
}
布局item_node_first.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:background="@drawable/ripple_item_select2">
<ImageView
android:id="@+id/ivIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
app:srcCompat="@drawable/baseline_keyboard_arrow_right_24" />
<TextView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/ivIcon"
android:text="一级标题0"
android:textColor="@color/black"
android:textSize="15dp" />
<View
android:layout_width="match_parent"
android:layout_height="0.8dp"
android:layout_alignParentBottom="true"
android:background="@color/veeeeee" />
RelativeLayout>
ripple_item_select2.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="@color/colorRipple" />
shape>
item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/bgColorPrimary" />
shape>
item>
selector>
箭头布局baseline_keyboard_arrow_right_24.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#C0C0C0"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z" />
vector>
第二个级节点提供类SecondProvider.kt
package com.example.myapplication3.adapter.node.tree.provider
import android.view.View
import com.chad.library.adapter.base.entity.node.BaseNode
import com.chad.library.adapter.base.provider.BaseNodeProvider
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.entity.node.tree.SecondNode
import kotlinx.android.synthetic.main.item_node_second.view.title
class SecondProvider : BaseNodeProvider() {
override val itemViewType: Int
get() = 2
override val layoutId: Int
get() = R.layout.item_node_second
override fun convert(helper: BaseViewHolder, data: BaseNode) {
val entity: SecondNode = data as SecondNode
helper.itemView.run { title.text = entity.title }
}
override fun onClick(helper: BaseViewHolder, view: View, data: BaseNode, position: Int) {
// val entity = data as SecondNode
// if (entity.isExpanded) {
// getAdapter()?.collapse(position)
// } else {
// getAdapter()?.expandAndCollapseOther(position)
// }
}
}
item_node_second.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_marginBottom="1dp"
android:background="#F7F7F7"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:src="@mipmap/ic_c" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@android:color/black"
android:textSize="15dp"/>
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center"
android:paddingRight="16dp"
android:src="@drawable/baseline_keyboard_arrow_right_24" />
LinearLayout>
第三个级节点提供类ThirdProvider.kt
package com.example.myapplication3.adapter.node.tree.provider
import com.chad.library.adapter.base.entity.node.BaseNode
import com.chad.library.adapter.base.provider.BaseNodeProvider
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.entity.node.tree.ThirdNode
import kotlinx.android.synthetic.main.item_node_third.view.title
class ThirdProvider : BaseNodeProvider() {
override val itemViewType: Int
get() = 3
override val layoutId: Int
get() = R.layout.item_node_third
override fun convert(helper: BaseViewHolder, data: BaseNode) {
val entity: ThirdNode = data as ThirdNode
helper.itemView.run { title.text = entity.title }
}
}
item_node_third.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E7E7E7">
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:layout_margin="10dp">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_centerHorizontal="true"
android:src="@mipmap/ic_c"/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/iv"
android:layout_centerHorizontal="true"
android:layout_marginTop="5.0dip"
android:text="测试"
android:textSize="@dimen/sp_14" />
RelativeLayout>
RelativeLayout>
第一个级列表FirstNode.java
package com.example.myapplication3.entity.node.tree;
import com.chad.library.adapter.base.entity.node.BaseExpandNode;
import com.chad.library.adapter.base.entity.node.BaseNode;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class FirstNode extends BaseExpandNode {
private List<BaseNode> childNode;
private String title;
public FirstNode(List<BaseNode> childNode, String title) {
this.childNode = childNode;
this.title = title;
setExpanded(false);
}
public String getTitle() {
return title;
}
@Nullable
@Override
public List<BaseNode> getChildNode() {
return childNode;
}
}
第二个级列表SecondNode.java
package com.example.myapplication3.entity.node.tree;
import com.chad.library.adapter.base.entity.node.BaseExpandNode;
import com.chad.library.adapter.base.entity.node.BaseNode;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class SecondNode extends BaseExpandNode {
private List<BaseNode> childNode;
private String title;
public SecondNode(List<BaseNode> childNode, String title) {
this.childNode = childNode;
this.title = title;
setExpanded(false);
}
public String getTitle() {
return title;
}
@Nullable
@Override
public List<BaseNode> getChildNode() {
return childNode;
}
}
第三个级列表ThirdNode.java
package com.example.myapplication3.entity.node.tree;
import com.chad.library.adapter.base.entity.node.BaseNode;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ThirdNode extends BaseNode {
private String title;
public ThirdNode(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
@Nullable
@Override
public List<BaseNode> getChildNode() {
return null;
}
}
ViewExt.kt
package com.example.myapplication3.ext
import android.view.View
import android.view.animation.DecelerateInterpolator
import androidx.core.view.ViewCompat
/**
* 旋转
* @param value 角度
* @param isAnimate 动画
*/
fun View.rotation(value:Float, isAnimate: Boolean){
if (isAnimate) {
ViewCompat.animate(this).setDuration(200)
.setInterpolator(DecelerateInterpolator())
.rotation(value)
.start()
} else {
this.rotation = value
}
}
MainActivity.kt
package com.example.myapplication3
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter.base.entity.node.BaseNode
import com.example.myapplication3.adapter.node.tree.NodeTreeAdapter
import com.example.myapplication3.entity.node.tree.FirstNode
import com.example.myapplication3.entity.node.tree.SecondNode
import com.example.myapplication3.entity.node.tree.ThirdNode
import kotlinx.android.synthetic.main.activity_main.rv_list
class MainActivity : AppCompatActivity() {
private val mAdapter by lazy {
NodeTreeAdapter().apply {
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
initData()
}
private fun initView() {
rv_list.layoutManager = GridLayoutManager(this@MainActivity, 4)
rv_list.adapter = mAdapter
}
private fun initData() {
mAdapter.setList(getEntity())
}
private fun getEntity(): MutableList<BaseNode>? {
val list: MutableList<BaseNode> = ArrayList()
for (i in 0..4) {
val secondNodeList: MutableList<BaseNode> = ArrayList()
if (i == 2) {
for (n in 0..1) {
val thirdNodeList: MutableList<BaseNode> = ArrayList()
for (t in 0..3) {
val node = ThirdNode("三级标题$t")
thirdNodeList.add(node)
}
val seNode = SecondNode(thirdNodeList, "二级标题$n")
seNode.isExpanded = true
secondNodeList.add(seNode)
}
} else {
val thirdNodeList: MutableList<BaseNode> = ArrayList()
for (t in 0..3) {
val node = ThirdNode("三级标题$t")
thirdNodeList.add(node)
}
val seNode = SecondNode(thirdNodeList, "二级标题0")
seNode.isExpanded = true
secondNodeList.add(seNode)
}
val entity = FirstNode(secondNodeList, "一级标题$i")
// 模拟 默认第0个是展开的
entity.isExpanded = false
list.add(entity)
}
return list
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"/>
LinearLayout>