在app
的build.gradle
在添加以下代码
1、implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
,这个里面带的适配器,直接调用就即可
BaseRecyclerViewAdapterHelper
简称BRVAH
Android SDK |
是否支持BaseRecyclerViewAdapterHelper:3.0.6 |
---|---|
android compileSdkVersion 29 |
是 |
android compileSdkVersion 30 |
是 |
android compileSdkVersion 31 |
是 |
android compileSdkVersion 32 |
是 |
android compileSdkVersion 33 |
是 |
这依赖包还需要得到要添加,在Project
的build.gradle
在添加以下代码,不添加就不行
allprojects {
repositories {
...
maven { url "https://jitpack.io" }//加上
}
}
2、AnyLayer:implementation "com.github.goweii:AnyLayer:4.1.4-androidx"
MySection.java
package com.example.myapplication3.entity;
import com.chad.library.adapter.base.entity.JSectionEntity;
public class MySection extends JSectionEntity {
private boolean isHeader;
private int headerNum;
private Object object;
private boolean isRecommend;
public MySection(boolean isHeader, int headerNum, Object object,boolean isRecommend) {
this.isHeader = isHeader;
this.headerNum = headerNum;
this.object = object;
this.isRecommend = isRecommend;
}
public Object getObject() {
return object;
}
@Override
public boolean isHeader() {
return isHeader;
}
public int getHeaderNum() {
return headerNum;
}
public boolean isRecommend() {
return isRecommend;
}
public void setRecommend(boolean recommend) {
isRecommend = recommend;
}
}
SectionQuickAdapter.kt
package com.example.myapplication3.adapter
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.graphics.Color
import android.text.Html
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.chad.library.adapter.base.BaseSectionQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.entity.MySection
import kotlinx.android.synthetic.main.def_section_head.view.*
import java.util.*
class SectionQuickAdapter(layoutResId: Int, sectionHeadResId: Int, data: MutableList<MySection>) :
BaseSectionQuickAdapter<MySection, BaseViewHolder>(sectionHeadResId, data) {
init {
setNormalLayout(layoutResId)
addChildClickViewIds(R.id.edit)
}
var selectedSize: Int = 0 //已选
var fixSize: Int = 0 //固定频道数目
var isRecommend: Boolean = true //当前是否显示推荐频道
var mLeft: Int = -1 //推荐频道蓝色线条距离屏幕左边的距离
var mRight: Int = -1 //城市频道蓝色线条距离屏幕左边的距离
var mTabY: Int = 0 //tab距离parent的Y的距离
// var onItemRangeChangeListener: SectionQuickAdapter.OnItemRangeChangeListener? = null
override fun convertHeader(helper: BaseViewHolder, item: MySection) {
helper.itemView.run {
when (item.headerNum) {
1 -> {
header.text = "我最喜欢 "
// enter.text = Html.fromHtml("按住拖动可以排序")
}
2 -> {
header.text = Html.fromHtml("全部频道 点击添加频道")
edit.visibility = View.GONE
}
}
}
}
override fun convert(holder: BaseViewHolder, item: MySection) {
setChannel(holder, holder.adapterPosition, item)
}
private fun setChannel(holder: BaseViewHolder, position: Int, item: MySection) {
var name = holder.getView<TextView>(R.id.item_textView)
var delete = holder.getView<ImageView>(R.id.delete)
var add = holder.getView<TextView>(R.id.tv_add)
name.text = item.`object` as String
name.setOnClickListener {
if (holder.layoutPosition < selectedSize + 1) {
//tab上面的 点击移除
if (holder.layoutPosition > fixSize) {
removeFromSelected(holder)
}
} else {
//tab下面的 点击添加到已选频道
selectedSize++
itemMove(holder.layoutPosition, selectedSize)
notifyItemChanged(selectedSize)
//刷新itemDecoration
// onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
}
}
name.setOnLongClickListener {
true
}
delete.setOnClickListener { removeFromSelected(holder) }
//tab下面及固定频道不显示删除按钮
if (position - 1 < fixSize || position > selectedSize) {
//************************新代码**********************
//固定频道的文字灰色
if (fixSize == position) {
name.setTextColor(Color.GRAY)
} else {
add.visibility = View.VISIBLE
}
//****************************************************
delete.visibility = View.GONE
} else {
delete.visibility = View.VISIBLE
//************************新代码**********************
add.visibility = View.GONE
//****************************************************
}
}
// private fun setTab(holder: ChannelAdapter.TabHolder) {
// holder.itemView.viewTreeObserver.addOnPreDrawListener(object :
// ViewTreeObserver.OnPreDrawListener {
// override fun onPreDraw(): Boolean {
// mTabY = holder.itemView.top
// return true
// }
//
// })
// }
private fun removeFromSelected(holder: BaseViewHolder) {
val delete = holder.getView<ImageView>(R.id.delete)
//************************新代码**********************
val add = holder.getView<TextView>(R.id.tv_add)
add.visibility = View.VISIBLE
//****************************************************
delete.visibility = View.GONE
val position = holder.layoutPosition
val bean = data[position]
if ((isRecommend && bean.isRecommend) || (!isRecommend && !bean.isRecommend)) {
//移除的频道属于当前tab显示的频道,直接调用系统方法移除
itemMove(position, selectedSize + 1)
notifyItemRangeChanged(selectedSize + 1, 1)
//刷新itemDecoration
// onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
} else {
//不属于当前tab显示的频道
removeAnimation(
holder.itemView,
(if (isRecommend) mRight else mLeft).toFloat(),
mTabY.toFloat(),
position
)
}
selectedSize--
}
private fun removeAnimation(view: View, x: Float, y: Float, position: Int) {
val fromX = view.left
val fromY = view.top
val animatorX = ObjectAnimator.ofFloat(view, "translationX", 0f, x - fromX)
val animatorY = ObjectAnimator.ofFloat(view, "translationY", 0f, y - fromY)
val alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f)
val set = AnimatorSet()
set.playTogether(animatorX, animatorY, alpha)
set.duration = 350
set.addListener(object : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationCancel(animation: Animator?) {
}
override fun onAnimationStart(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
data.add(0, data[position])
data.removeAt(position)
notifyItemRemoved(position)
// onItemRangeChangeListener?.let { onItemRangeChangeListener!!.refreshItemDecoration() }
//这里需要重置view的属性
resetView(view, x - fromX, y - fromY)
}
})
set.start()
}
private fun resetView(view: View, toX: Float, toY: Float) {
val animatorX = ObjectAnimator.ofFloat(view, "translationX", -toX, 0f)
val animatorY = ObjectAnimator.ofFloat(view, "translationY", -toY, 0f)
val alpha = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f)
val set = AnimatorSet()
set.playTogether(animatorX, animatorY, alpha)
set.duration = 0
set.startDelay = 5
set.start()
}
fun itemMove(fromPosition: Int, toPosition: Int) {
if (fromPosition < toPosition) {
for (i in fromPosition until toPosition) {
Collections.swap(data, i, i + 1)
}
} else {
for (i in fromPosition downTo toPosition + 1) {
Collections.swap(data, i, i - 1)
}
}
notifyItemMoved(fromPosition, toPosition)
}
}
item
拖拽,文件DragTouchHelper.kt
package com.example.myapplication3.widget
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.graphics.drawable.GradientDrawable
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.dragswipe.DragAndSwipeCallback
import com.chad.library.adapter.base.module.BaseDraggableModule
import com.example.myapplication3.R
import com.example.myapplication3.past.ChannelRvAdapter1
import com.example.myapplication3.past.DragAdapter
import com.example.myapplication3.adapter.SectionQuickAdapter
import com.example.myapplication3.entity.MySection
import java.util.*
/**
* GitHub : https://github.com/yechaoa
* CSDN : http://blog.csdn.net/yechaoa
*
* Created by yechao on 2022/7/17.
* Describe :
*/
class ItemDragCallback2(var mAdapter: SectionQuickAdapter, var mPadding: Int) : ItemTouchHelper.Callback()
{
private val mPaint: Paint = Paint()
init {
mPaint.color = Color.GRAY
mPaint.isAntiAlias = true
mPaint.strokeWidth = 1f
mPaint.style = Paint.Style.STROKE
val pathEffect = DashPathEffect(FloatArray(2, { 5f }), 5f)
mPaint.pathEffect = pathEffect
}
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
//固定位置及tab下面的channel不能拖动
val position = viewHolder!!.layoutPosition
if (position < mAdapter.fixSize + 1 || position > mAdapter.selectedSize) {
return makeMovementFlags(0, 0)
}
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
return makeMovementFlags(dragFlags, 0)
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val fromPosition = viewHolder!!.layoutPosition //拖动的位置
val toPosition = target!!.layoutPosition //释放的位置
//固定位置及tab下面的channel不能移动
if (toPosition < mAdapter.fixSize + 1 || toPosition > mAdapter.selectedSize) {
return false
}
mAdapter.itemMove(fromPosition, toPosition)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
//滑动重写这里
}
override fun onChildDrawOver(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder?, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
// if (dX != 0f && dY != 0f || isCurrentlyActive) {
// //长按拖拽时底部绘制一个虚线矩形
// c!!.drawRect(viewHolder!!.itemView.left.toFloat(), (viewHolder.itemView.top - mPadding).toFloat(), viewHolder.itemView.right.toFloat(), viewHolder.itemView.bottom.toFloat(), mPaint)
// }
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
//长按时调用 设置颜色 阴影
// val holder = viewHolder as ChannelAdapter.ChannelHolder
// holder.name.setBackgroundColor(Color.parseColor("#FDFDFE"))
// holder.delete.visibility= View.GONE
// holder.name.elevation=5f
//*******新代码********
super.onSelectedChanged(viewHolder, actionState)
//*******新代码********
}
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
//重置view
// val holder=viewHolder as ChannelAdapter.ChannelHolder
// holder.name.setBackgroundColor(Color.parseColor("#f0f0f0"))
// holder.delete.visibility= View.VISIBLE
// holder.name.elevation=0f
//*******新代码********
super.clearView(recyclerView, viewHolder)
//*******新代码********
}
}
ChannelActivity.kt
package com.example.myapplication3.channel
import android.os.Bundle
import android.view.Gravity
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication3.R
import com.example.myapplication3.adapter.SectionQuickAdapter
import com.example.myapplication3.entity.MySection
import com.example.myapplication3.widget.ItemDragCallback2
import kotlinx.android.synthetic.main.activity_channel.*
import per.goweii.anylayer.AnyLayer
import per.goweii.anylayer.dialog.DialogLayer
import per.goweii.anylayer.dialog.DialogLayer.OutsideTouchedListener
import per.goweii.anylayer.widget.SwipeLayout
class ChannelActivity : AppCompatActivity()
// , SectionQuickAdapter.OnItemRangeChangeListener
{
private var mRecyclerView: RecyclerView? = null
companion object {
private var SPAN_COUNT = 4
}
private var list: MutableList<MySection> = ArrayList()
private var itemTouchHelper: ItemTouchHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_channel)
button.setOnClickListener {
showRadListDialog(initData())
}
}
private fun showRadListDialog(mList: MutableList<MySection>) {
val rvDialog = AnyLayer.dialog()
.contentView(R.layout.activity_section_uer)
.backgroundDimDefault()
.gravity(Gravity.BOTTOM)
.swipeDismiss(SwipeLayout.Direction.BOTTOM)
.animStyle(DialogLayer.AnimStyle.BOTTOM)
.backgroundDimAmount(0.5F)//背景变暗的程度0~1,直接调用到这函数里看文档就即可
rvDialog.outsideTouched(OutsideTouchedListener {
mList.clear()
})
rvDialog.show()
mRecyclerView = rvDialog.getView<RecyclerView>(R.id.rv_list)
mRecyclerView?.layoutManager = GridLayoutManager(this, SPAN_COUNT)
val mAdapter = SectionQuickAdapter(R.layout.item_drag_grid, R.layout.def_section_head, mList)
// val animator = DefaultItemAnimator()
// animator.moveDuration = 400 //设置动画时间
// animator.removeDuration = 0
// mRecyclerView?.itemAnimator = animator
mRecyclerView?.adapter = mAdapter
mAdapter.fixSize = 1
mAdapter.selectedSize = 10 //点击进入频道下面的频道数
// mAdapter.onItemRangeChangeListener = this
// 设置拖拽
val dragCallBack = ItemDragCallback2(mAdapter,2)
itemTouchHelper = ItemTouchHelper(dragCallBack)
itemTouchHelper!!.attachToRecyclerView(mRecyclerView)
}
private fun initData(): MutableList<MySection> {
list.add(MySection(true, 1, "我最喜欢 点击进入频道", false))
list.add(MySection(false, 0, "测试1", true))
list.add(MySection(false, 0, "测试2", true))
list.add(MySection(false, 0, "测试3", true))
list.add(MySection(false, 0, "测试4", true))
list.add(MySection(false, 0,"测试5",true))
list.add(MySection(false, 0,"测试6",true))
list.add(MySection(false, 0,"测试7",true))
list.add(MySection(false, 0,"测试8",true))
list.add(MySection(false, 0,"测试9",true))
list.add(MySection(false, 0,"测试10",true))
list.add(MySection(true, 2, "全部频道 点击添加频道", false))
list.add(MySection(false, 0, "测试11", true))
list.add(MySection(false, 0, "测试12", true))
list.add(MySection(false, 0, "测试13", true))
list.add(MySection(false, 0, "测试14", true))
list.add(MySection(false, 0,"测试15",true))
list.add(MySection(false, 0,"测试16",true))
list.add(MySection(false, 0,"测试17",true))
list.add(MySection(false, 0,"测试18",true))
list.add(MySection(false, 0,"测试19",true))
list.add(MySection(false, 0,"测试20",true))
return list
}
// override fun refreshItemDecoration() {
// mRecyclerView?.invalidateItemDecorations()
// }
}
activity_section_uer.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="700dp"
android:background="@color/white">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
LinearLayout>
item_drag_grid.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="75dp"
android:layout_height="50dp">
<TextView
android:id="@+id/item_textView"
android:layout_width="60dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:background="@drawable/shape_radius5_green"
android:gravity="center"
android:text="测试"
android:textColor="@color/black"
android:textSize="13dp"/>
<ImageView
android:id="@+id/delete"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentRight="true"
android:src="@mipmap/delete"
android:visibility="visible"/>
<TextView
android:id="@+id/tv_add"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignRight="@id/item_textView"
android:layout_alignParentRight="true"
android:layout_marginTop="8dp"
android:text="+"
android:visibility="gone"/>
RelativeLayout>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/bg" />
<corners android:radius="5dp" />
shape>
<color name="bg">#E7E7E7color>
def_section_head.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:padding="10dp">
<TextView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="已选频道 "
android:textStyle="bold"/>
<TextView
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textColor="@color/red"
android:text="按住拖动可以排序" />
RelativeLayout>