Android kotlin 仿QQ侧滑右置顶(取消置顶)与删除功能(RecyclerView+BRVAH3.0.6+androidx+SwipeMenuLayout)

一、实现效果

二、引入依赖

appbuild.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

这依赖包还需要得到要添加,在Projectbuild.gradle在添加以下代码,不添加就不行

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }//加上
    }
}

2、侧滑菜单:implementation 'com.github.ljphawk:SwipeMenuLayout:1.01'

三、实现源码

1、实体类

列表itemnum值和top文本,SlidingItembean.xml

package com.example.myapplication3;

public class SlidingItembean {

	private String num;
	private String name;
	private String path;
	private String setTop;

	public SlidingItembean() {
		super();
	}

	public SlidingItembean(String num, String name, String path, String setTop) {
		super();
		this.num = num;
		this.name = name;
		this.path = path;
		this.setTop = setTop;
	}



	public String getSetTop() {
		return setTop;
	}



	public void setSetTop(String setTop) {
		this.setTop = setTop;
	}



	public String getNum() {
		return num;
	}

	public void setNum(String num) {
		this.num = num;
	}

	public String getName() {
		return name;
	}

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

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

}

2、适配器

RvAdapter.kt

package com.example.myapplication3.adapter

import cn.ljp.swipemenu.SwipeMenuLayout
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.SlidingItembean
import kotlinx.android.synthetic.main.item.view.*

class RvAdapter(layoutResId: Int = R.layout.item) :
    BaseQuickAdapter<SlidingItembean, BaseViewHolder>(layoutResId) {

    //侧滑右顶置
    private var mFirstOnItemClickListener: FirstOnItemClickListener? = null

    private var mOnItemClickListener: OnItemClickListener? = null

    override fun convert(holder: BaseViewHolder, item: SlidingItembean) {
        val mSwipe: SwipeMenuLayout = holder.getView(R.id.swipe_menu_layout)

        //侧滑右删
        mSwipe.setEnableRightSwipe(false)

        //侧滑左删
//        mSwipe.setEnableRightSwipe(true)

        holder.itemView.run {

            tv_content.text = item.num

            if (item.setTop.equals("取消置顶")){
                swipe_menu_layout.setBackgroundColor(resources.getColor(R.color.colorRipple))
            }else if (item.setTop.equals("置顶")){
                swipe_menu_layout.setBackgroundColor(resources.getColor(R.color.white))
            }

            tv_toFirst.text = item.setTop

            //侧滑右置顶
            tv_toFirst.setOnClickListener {
                mFirstOnItemClickListener!!.firstOnItemClickListener(holder)
            }

            //侧滑右删除
            tv_menu2.setOnClickListener {
                mOnItemClickListener!!.onItemClickListener(holder)
            }
        }
    }

    fun setFirstOnItemClickListener(firstOnItemClickListener: FirstOnItemClickListener) {
        this.mFirstOnItemClickListener = firstOnItemClickListener
    }

    fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
        this.mOnItemClickListener = onItemClickListener
    }

    interface FirstOnItemClickListener {
        fun firstOnItemClickListener(holder: BaseViewHolder)
    }

    interface OnItemClickListener {
        fun onItemClickListener(holder: BaseViewHolder)
    }
}

item布局item.xml

<?xml version="1.0" encoding="utf-8"?>
<cn.ljp.swipemenu.SwipeMenuLayout
    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:id="@+id/swipe_menu_layout"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@color/white"
    app:isClickMenuAndClose="false"
    app:isEnableLeftMenu="false"
    app:isEnableSwipe="true"
    app:isOpenChoke="true"
    tools:ignore="MissingDefaultResource">

    <RelativeLayout
        android:id="@+id/ll_item"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
        <!--也可以是复杂的item布局-->
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"/>
    </RelativeLayout>

    <TextView
        android:id="@+id/tv_toFirst"
        android:layout_width="60dp"
        android:layout_height="match_parent"
        android:background="#2196F3"
        android:gravity="center"
        android:text="顶置"/>

    <TextView
        android:id="@+id/tv_menu2"
        android:layout_width="60dp"
        android:layout_height="match_parent"
        android:background="#f00"
        android:gravity="center"
        android:text="删除"
        android:textColor="#fff"/>
</cn.ljp.swipemenu.SwipeMenuLayout>
<color name="white">#FFFFFFFF</color>

在这里插入图片描述

<color name="colorRipple">#E2E2E2</color>
<color name="white">#FFFFFFFF</color>

在这里插入图片描述

3、代码解析和画解

1、获取数据numsetTop
在这里插入图片描述
num显示在item

“取消置顶”itemnum值是从大到小,“置顶”item的值是从小到大,仿QQ的“取消置顶”时间也是从大到小

numString可以转换成Int

		var num = mAdapter.data[position].num.toInt()

1、置顶

1、如果列表某一个itemnum值是0top文本是“置顶”,就直接把该item插入它的上面,没有什么其他的

		if (mAdapter.data[position].num.toInt() == 0 && mAdapter.data[position].setTop.equals("置顶")) {
            mAdapter.data[position].setTop = "取消置顶"
            mAdapter.data.add(position + 1, mAdapter.data[position])
            mAdapter.data.removeAt(position)
            mAdapter.notifyDataSetChanged()
            return
        }

2、如果全部列表itemtop文本都是“置顶”,就直接把该item插入首位,没有什么其他的

		var j = 0
        for (i in 0..mAdapter.data.size) {
            if (j == mAdapter.data.size) {
                mAdapter.data[position].setTop = "取消置顶"
                mAdapter.data.add(0, mAdapter.data[position])
                mAdapter.data.removeAt(position + 1)
                mAdapter.notifyDataSetChanged()
                return
            }
            if (i == mAdapter.data.size) break
            if (mAdapter.data[i].setTop.equals("置顶")) {
                j++
            }
        }

如果点击itemnum值是3

3、如果某一个itemnum值大于首位一个itemnum值,并且某一个itemtop文本为“置顶”和首位一个itemtop文本是“取消置顶”,就直接把该item插入首位,没有什么其他的

		if (mAdapter.data[position].num.toInt() > mAdapter.data[0].num.toInt() && mAdapter.data[0].setTop.equals("取消置顶")) {
            mAdapter.data[position].setTop = "取消置顶"
            mAdapter.data.add(0, mAdapter.data[position])
            mAdapter.data.removeAt(position + 1)
            mAdapter.notifyDataSetChanged()
            return
        }

如果点击itemnum值是4

4、如果某一个itemnum值小于最后到首位的哪一个itemnum值,并且哪一个itemtop文本为“取消置顶”,就把该item插入哪一个itemtop文本“取消置顶”下面,注意:需要在上面第3个下可以解决

		var num = mAdapter.data[position].num.toInt()
//        for (i in 0 until mAdapter.data.size)
        for (i in mAdapter.data.size - 1 downTo 0) {
//            if (num < mAdapter.data[i].num.toInt() && num > mAdapter.data[i+1].num.toInt() && mAdapter.data[i].setTop.equals("取消置顶") && mAdapter.data[i+1].num.equals("取消置顶")) {
            if (num < mAdapter.data[i].num.toInt() && mAdapter.data[i].setTop.equals("取消置顶")) {
                mAdapter.data[position].setTop = "取消置顶"
                mAdapter.data.add(i + 1, mAdapter.data[position])
                mAdapter.data.removeAt(position + 1)
                mAdapter.notifyDataSetChanged()
                break
            }
        }

如果点击itemnum值是2

2、取消置顶

1、如果列表某一个itemnum值是0top文本是“取消置顶”,就直接把该item插入“置顶”首位,没有什么其他的

		if (mAdapter.data[position].num.toInt() == 0) {
            for (i in mAdapter.data.indices) {
                if (mAdapter.data[i].setTop.equals("置顶")) {
                    mAdapter.data[position].setTop = "置顶"
                    mAdapter.data.add(i, mAdapter.data[position])
                    mAdapter.data.removeAt(position)
                    mAdapter.notifyDataSetChanged()
                    return
                }
            }
        }

2、如果全部列表itemtop文本都是“取消置顶”,就直接把该item插入底部设置为“置顶”,没有什么其他的

		var j = 0
        for (i in 0..mAdapter.data.size) {
            if (j == mAdapter.data.size) {
                mAdapter.data[position].setTop = "置顶"
                mAdapter.data.add(mAdapter.data.size, mAdapter.data[position])
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
                return
            }
            if (i == mAdapter.data.size) break
            if (mAdapter.data[i].setTop.equals("取消置顶")) {
                j++
            }
        }

如果列表数是4,某一个itemnum值是2

3、如果某一个itemnum值大于最后一个itemnum值,并且最后一个itemtop文本是“置顶”,就直接把该item插入底部,没有什么其他的

		if (mAdapter.data[position].num.toInt() > mAdapter.data[mAdapter.data.size - 1].num.toInt() && mAdapter.data[mAdapter.data.size - 1].setTop.equals("置顶")) {
            mAdapter.data[position].setTop = "置顶"
            mAdapter.data.add(mAdapter.data.size, mAdapter.data[position])
            mAdapter.data.removeAt(position)
            mAdapter.notifyDataSetChanged()
            return
        }

如果列表数是4,某一个itemnum值是2

4、如果某一个itemnum值小于首位到最后的哪一个itemnum值,并且哪一个itemtop文本为“置顶”,就把该item插入哪一个itemtop文本“置顶”上面,注意:需要在上面第3个下可以解决

		var num = mAdapter.data[position].num.toInt()
        for (i in 0 until mAdapter.data.size) {
            if (num < mAdapter.data[i].num.toInt() && mAdapter.data[i].setTop.equals("置顶")) {
                mAdapter.data[position].setTop = "置顶"
                mAdapter.data.add(i, mAdapter.data[position])
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
                break
            }
        }

如果列表数是4,某一个itemnum值是2

4、实现视图

完整MainActivity.kt代码

package com.example.myapplication3

import android.app.Activity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.adapter.RvAdapter
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : Activity(), RvAdapter.FirstOnItemClickListener, RvAdapter.OnItemClickListener {

    private val mAdapter by lazy {
        RvAdapter()
    }

    private val list: MutableList<SlidingItembean> = ArrayList()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initData()
        initEvent()
    }

    private fun initEvent() {
        recyclerView.adapter = mAdapter
        mAdapter.setList(list)
        mAdapter.setFirstOnItemClickListener(this)
        mAdapter.setOnItemClickListener(this)
    }

    private fun initData() {
        for (i in 0..3) {
            var slidingItembean: SlidingItembean? = null
            slidingItembean = SlidingItembean("$i", "", "", "置顶")
            list.add(slidingItembean)
        }
    }

    /**
     * 初始化界面
     */
    private fun initView() {
        val layoutManager = LinearLayoutManager(this@MainActivity)
        layoutManager.orientation = LinearLayoutManager.VERTICAL
        recyclerView.layoutManager = layoutManager
    }

    /**
     * 取消置顶
     * @param position
     */
    private fun unSetTop(position: Int) {
        var isAdd = false

        /** 差值  */
        var min = 9999999

        /** 当前position的数值  */
//        val num: Int

//        var num: Int

        // 差值最小处的行数
        var j = 0
        var num2 = 0
        var jumpNum = 0
        mAdapter.data[position].setTop = "置顶"

        var num = mAdapter.data[position].num.toInt()

        // list长度为2特殊处理
        if (mAdapter.data.size == 2) {
            // 第一行确定为取消置顶
            if (mAdapter.data[1].setTop.equals("取消置顶")) {
                if (position == 0) {
                    if (num == 0) {
                        mAdapter.data.add(2, mAdapter.data[position])
                    }
                    if (num == 1) {
                        mAdapter.data.add(2, mAdapter.data[position])
                    }

//                    list.removeAt(position)
                    mAdapter.data.removeAt(position)

                    mAdapter.notifyDataSetChanged()
                } else {
                    mAdapter.data.add(2, mAdapter.data[position])
                    mAdapter.data.removeAt(position)
                    mAdapter.notifyDataSetChanged()
                }
            } else {
                if (num == 0) {
                    mAdapter.data.add(1, mAdapter.data[position])
                }
                if (num == 1) {
                    mAdapter.data.add(2, mAdapter.data[position])
                }
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
            }
        } else {

            //for (i in mAdapter.data.indices)
            for (i in 0 until mAdapter.data.size) {

                if (num < mAdapter.data[i].num.toInt() && mAdapter.data[i].setTop.equals("置顶")) {
                    mAdapter.data.add(i, mAdapter.data[position])
                    isAdd = true
                    break
                }


                if (i + 1 != mAdapter.data.size) {
                    if (num > mAdapter.data[i].num.toInt() && num < mAdapter.data[i + 1].num.toInt()) {
                        mAdapter.data.add(i + 1, mAdapter.data[position])
                        isAdd = true
                        break
                    }
                } else {
                    mAdapter.data.add(i + 1, mAdapter.data[position])
                    isAdd = true
                    break
                }
            }

            // 如果没有比自己小的值 例如0 则isAdd=false
            // 遍历list 寻找差值最小的地方插入list
            if (!isAdd) {
//                for (i in mAdapter.data.indices)
                for (i in 0 until mAdapter.data.size) {
                    if (i == position || mAdapter.data[i].setTop.equals("取消置顶")) {
                        // 排除与自身相比较
                        // 排除置顶item比较
                        Log.i("TAG", "调过$i")
                        jumpNum++
                        if (jumpNum == mAdapter.data.size) {
                            j = mAdapter.data.size
                        }
                        continue
                    }
                    num2 = mAdapter.data[i].num.toInt()
                    if (num2 - num < min) {
                        min = num2 - num
                        // 记录行号
                        j = i
                        Log.i("TAG", "插入行数J=$j")
                    }
                }
                // 遍历完成后拿到差值min
                val number = min + num
                mAdapter.data.add(j, mAdapter.data[position])
                Log.i("TAG", "*********插入行数J=$j")
            }
            mAdapter.data.removeAt(position)
            mAdapter.notifyDataSetChanged()
        }
    }

    //取消置顶
    private fun unSetTop2(position: Int) {

        //1、如果列表某一个item的num值是0,top文本是“取消置顶”,就直接把该item插入“置顶”首位,没有什么其他的
        if (mAdapter.data[position].num.toInt() == 0) {
            for (i in mAdapter.data.indices) {
                if (mAdapter.data[i].setTop.equals("置顶")) {
                    mAdapter.data[position].setTop = "置顶"
                    mAdapter.data.add(i, mAdapter.data[position])
                    mAdapter.data.removeAt(position)
                    mAdapter.notifyDataSetChanged()
                    return
                }
            }
        }

        //2、如果列表item的top文本都是“取消置顶”,不用数一下就直接把该item插入底部
        var j = 0
        for (i in 0..mAdapter.data.size) {
            if (j == mAdapter.data.size) {
                mAdapter.data[position].setTop = "置顶"
                mAdapter.data.add(mAdapter.data.size, mAdapter.data[position])
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
                return
            }
            if (i == mAdapter.data.size) break
            if (mAdapter.data[i].setTop.equals("取消置顶")) {
                j++
            }
        }

        //3、如果某一个item的num值大于最后一个item的num值,并且最后一个item的top文本是“置顶”,不用数一下就直接把该item插入底部
        if (mAdapter.data[position].num.toInt() > mAdapter.data[mAdapter.data.size - 1].num.toInt() && mAdapter.data[mAdapter.data.size - 1].setTop.equals("置顶")) {
            mAdapter.data[position].setTop = "置顶"
            mAdapter.data.add(mAdapter.data.size, mAdapter.data[position])
            mAdapter.data.removeAt(position)
            mAdapter.notifyDataSetChanged()
            return
        }

        //4、如果某一个item的num值小于首位到最后的哪一个item的num值,并且哪一个item的top文本为“置顶”,就把该item插入哪一个item的top文本“置顶”上面,注意:需要在上面第3个下可以解决
        var num = mAdapter.data[position].num.toInt()
        for (i in 0 until mAdapter.data.size) {
            if (num < mAdapter.data[i].num.toInt() && mAdapter.data[i].setTop.equals("置顶")) {
                mAdapter.data[position].setTop = "置顶"
                mAdapter.data.add(i, mAdapter.data[position])
                mAdapter.data.removeAt(position)
                mAdapter.notifyDataSetChanged()
                break
            }
        }
    }

    /**
     * 置顶
     * @param position
     */
    private fun setTop(position: Int) {
        mAdapter.data[position].setTop = "取消置顶"
        mAdapter.data.add(0, mAdapter.data[position])

        // 置顶后list.size增加一 所以要position+1
        mAdapter.data.removeAt(position + 1)
        mAdapter.notifyDataSetChanged()
    }

    //置顶
    private fun setTop2(position: Int) {

        //1、如果列表某一个item的num值是0,top文本是“置顶”,就直接把该item插入它的上面,没有什么其他的
        if (mAdapter.data[position].num.toInt() == 0 && mAdapter.data[position].setTop.equals("置顶")) {
            mAdapter.data[position].setTop = "取消置顶"
            mAdapter.data.add(position + 1, mAdapter.data[position])
            mAdapter.data.removeAt(position)
            mAdapter.notifyDataSetChanged()
            return
        }

        //2、如果列表item的top文本都是“置顶”,不用数一下就直接把该item插入首位
        var j = 0
        for (i in 0..mAdapter.data.size) {
            if (j == mAdapter.data.size) {
                mAdapter.data[position].setTop = "取消置顶"
                mAdapter.data.add(0, mAdapter.data[position])
                mAdapter.data.removeAt(position + 1)
                mAdapter.notifyDataSetChanged()
                return
            }
            if (i == mAdapter.data.size) break
            if (mAdapter.data[i].setTop.equals("置顶")) {
                j++
            }
        }

        //3、如果某一个item的num值大于首位一个item的num值,并且某一个item的top文本为“置顶”和首位一个item的top文本是“取消置顶”,不用数一下就直接把该item插入首位
        if (mAdapter.data[position].num.toInt() > mAdapter.data[0].num.toInt() && mAdapter.data[0].setTop.equals("取消置顶")) {
            mAdapter.data[position].setTop = "取消置顶"
            mAdapter.data.add(0, mAdapter.data[position])
            mAdapter.data.removeAt(position + 1)
            mAdapter.notifyDataSetChanged()
            return
        }

        //4、如果某一个item的num值小于首位到最后的哪一个item的num值,并且哪一个item的top文本为“取消置顶”,就把该item插入哪一个item的top文本“取消置顶”下面,注意:需要在上面第3个下可以解决
        var num = mAdapter.data[position].num.toInt()
//        for (i in 0 until mAdapter.data.size)
        for (i in mAdapter.data.size - 1 downTo 0) {
//            if (num < mAdapter.data[i].num.toInt() && num > mAdapter.data[i+1].num.toInt() && mAdapter.data[i].setTop.equals("取消置顶") && mAdapter.data[i+1].num.equals("取消置顶")) {
            if (num < mAdapter.data[i].num.toInt() && mAdapter.data[i].setTop.equals("取消置顶")) {
                mAdapter.data[position].setTop = "取消置顶"
                mAdapter.data.add(i + 1, mAdapter.data[position])
                mAdapter.data.removeAt(position + 1)
                mAdapter.notifyDataSetChanged()
                break
            }
        }
    }

    //侧滑右置顶
    override fun firstOnItemClickListener(holder: BaseViewHolder) {
        if (mAdapter.data[holder.adapterPosition].setTop.equals("置顶")) {
            setTop2(holder.adapterPosition)
//            setTop(holder.adapterPosition)
        } else if (mAdapter.data[holder.adapterPosition].setTop.equals("取消置顶")) {
            unSetTop2(holder.adapterPosition)
        }
    }

    //侧滑右删除
    override fun onItemClickListener(holder: BaseViewHolder) {
        mAdapter.data.removeAt(holder.adapterPosition)
        mAdapter.notifyDataSetChanged()
    }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dyk="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#fff4f7f9"
        android:cacheColorHint="#00000000"
        android:divider="#dddbdb"
        android:dividerHeight="1dp"
        dyk:right_width="120dp" />
</RelativeLayout>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬sir哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值