Android kotlin 用RecyclerView(androidx+BRVAH3.0.6)实现从底部弹出列表对话框(单选/多选)功能

一、实现效果

二、引入依赖

appbuild.gradle在添加以下代码
1、框架弹窗AnyLayer(github官网):implementation "com.github.goweii:AnyLayer:4.1.4-androidx"
2、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" }//加上
    }
}

三、实现源码

1、实体类

单选/多选Dict.java

package com.example.myapplication3.data;

public class Dict {
    private String dataName;
    private String dataValue;

    public Dict(String dataName, String dataValue) {
        this.dataName = dataName;
        this.dataValue = dataValue;
    }

    public String getDataName() {
        return dataName;
    }

    public void setDataName(String dataName) {
        this.dataName = dataName;
    }

    public String getDataValue() {
        return dataValue;
    }

    public void setDataValue(String dataValue) {
        this.dataValue = dataValue;
    }
}

2、适配器单选/多选

单选RvRadioAdapter.kt

package com.example.myapplication3.adapter

import android.graphics.Color
import android.view.View
import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.data.Dict

//单选
class RvRadioAdapter(var selValue: String, layoutResId: Int = R.layout.item_rad) :
    BaseQuickAdapter<Dict, BaseViewHolder>(layoutResId) {


    override fun convert(helper: BaseViewHolder, item: Dict) {

        var tvName = helper.getView<TextView>(R.id.tvName)
        var tvSelected = helper.getView<TextView>(R.id.tvSelected)

        tvName.text = item.dataName
        // 根据选中状态更新UI
        tvName.setTextColor(context.resources.getColor(R.color.v666666))//<color name="v666666">#666666</color>
        tvSelected.visibility = View.GONE

        if(item.dataValue.equals(selValue)){
            tvName.setTextColor(context.resources.getColor(R.color.red))
            tvSelected.visibility = View.VISIBLE
        }
    }

    fun getSelectIndex(): Int {
        var index = 0
        data.forEachIndexed { i, dict ->
            if(dict.dataValue == selValue){
                index = i
                return@forEachIndexed
            }
        }
        return index
    }
}

多选RvMCAdapter.kt

package com.example.myapplication3.adapter

import android.view.View
import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
import com.example.myapplication3.data.Dict


//多选
class RvMCAdapter(var sels:MutableSet<Dict>, layoutResId: Int = R.layout.item_rad) :
        BaseQuickAdapter<Dict, BaseViewHolder>(layoutResId) {

    override fun convert(helper: BaseViewHolder, item: Dict) {

        var tvName = helper.getView<TextView>(R.id.tvName)
        var tvSelected = helper.getView<TextView>(R.id.tvSelected)

        tvName.text = item.dataName
        // 根据选中状态更新UI
        tvName.setTextColor(context.resources.getColor(R.color.v666666))
        tvSelected.visibility = View.GONE

        if(sels.contains(item)){
            tvName.setTextColor(context.resources.getColor(R.color.red))
            tvSelected.visibility = View.VISIBLE
        }

    }

    fun  setCheckSelValue(sels: MutableSet<Dict>){
        this.sels = sels
        notifyDataSetChanged()
    }
}

单选/多选item布局item_rad.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@color/white"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    android:gravity="center">

    <!--<color name="v666666">#666666</color>-->
    <TextView
        android:id="@+id/tvName"
        android:text="text"
        android:textColor="@color/v666666"
        android:textSize="15sp"
        android:paddingStart="20dp"
        android:paddingEnd="8dp"
        android:gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="45dp"
        android:paddingLeft="20dp"
        android:paddingRight="8dp" />

    <TextView
        android:id="@+id/tvSelected"
        android:text="@string/checked"
        android:layout_toEndOf="@+id/tvName"
        android:textSize="15sp"
        android:visibility="gone"
        android:textColor="@color/red"
        android:gravity="center_vertical"
        android:layout_width="wrap_content"
        android:layout_height="45dp"
        android:layout_toRightOf="@+id/tvName" />

    <!--<color name="veeeeee">#eeeeee</color>-->
    <View
        android:background="@color/veeeeee"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="0.5dp"/>
</RelativeLayout>

3、框架弹窗AnyLayer单选/多选

DialogUtil.kt

package com.example.myapplication3.util

import android.view.Gravity
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.isGone
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication3.R
import com.example.myapplication3.adapter.RvMCAdapter
import com.example.myapplication3.adapter.RvRadioAdapter
import com.example.myapplication3.data.Dict
import per.goweii.anylayer.AnyLayer
import per.goweii.anylayer.widget.SwipeLayout

/**
 * 底部弹出的列表对话框(单选)
 */
fun showRadioListDialog(
    title: String?,
    selValue: String?,
    dictList: List<Dict>,
    callback: OnResultCallback<String>
) {
    val dialog = AnyLayer.dialog()
        .contentView(R.layout.dialog_rad_list)
        .backgroundDimDefault()
        .gravity(Gravity.BOTTOM)
        .swipeDismiss(SwipeLayout.Direction.BOTTOM)
        .onClickToDismiss(R.id.flFork)

    dialog.show()

    val mAdapter = RvRadioAdapter(selValue ?: "").apply{
        setOnItemClickListener { _, _, position ->
            val dict = getItem(position)

            if(dict.dataValue.equals(selValue)){
                dict.dataValue = ""
            }

            callback.onResult(dict.dataName)
            dialog.dismiss()
        }
    }
    dialog.getView<TextView>(R.id.title)?.text = title?:""
    dialog.getView<RecyclerView>(R.id.mRecyclerView)?.apply {
//        setMaxHeight(getScreenPix().heightPixels * 1 / 2)
        adapter = mAdapter
        mAdapter.setList(dictList)
        val pos = mAdapter.getSelectIndex()
        scrollToPosition(pos)
    }
}

/**
 * 底部弹出的列表对话框(多选)
 */
fun showMCListDialog(
    title: String?,
    selname: String,
    dictList: List<Dict>,
    callback: OnResultCallback<String>
) {
    val dialog = AnyLayer.dialog()
        .contentView(R.layout.dialog_rad_list)
        .backgroundDimDefault()
        .gravity(Gravity.BOTTOM)
        .swipeDismiss(SwipeLayout.Direction.BOTTOM)
        .onClickToDismiss(R.id.flFork)
    dialog.show()

    val sels = mutableSetOf<Dict>()
    val names = selname.split(",")
    dictList.forEach {
        if(names.contains(it.dataName)){
            sels.add(it)
        }
    }

    val mAdapter = RvMCAdapter(sels).apply{
        setOnItemClickListener { parent, view, position ->
            val dict = getItem(position)

            if(sels.contains(dict)){
                sels.remove(dict)
            }else{
                sels.add(dict)
            }
            setCheckSelValue(sels)
        }
    }

    dialog.getView<TextView>(R.id.title)?.text = title?:""
    dialog.getView<RecyclerView>(R.id.mRecyclerView)?.apply {
//        setMaxHeight(getScreenPix().heightPixels * 1 / 2)
        adapter = mAdapter

        mAdapter.setList(dictList)
    }

    dialog.getView<LinearLayout>(R.id.ll_dialog_confirm)?.isGone = false
    dialog.getView<TextView>(R.id.tv_dialog_confirm)?.setOnClickListener {

        var valueBuilder =  StringBuilder()
        sels.forEach {
//            valueBuilder.append("|$" + it.dataValue + "$");
            valueBuilder.append(it.dataName);
        }
//        if(valueBuilder.isNotEmpty()){
//            valueBuilder = valueBuilder.deleteCharAt(0)
//        }

        dialog.dismiss()
        callback.onResult(valueBuilder.toString())
    }
}

interface OnResultCallback<T> {
    fun onResult(t: T)
}

Dialogitem布局dialog_rad_list.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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingTop="@dimen/dp_10"
        android:paddingBottom="@dimen/dp_10"
        android:gravity="center_vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="33dp"
            android:layout_centerInParent="true"
            android:layout_toLeftOf="@id/flFork"
            android:textColor="#333333"
            android:gravity="center"
            android:textStyle="bold"
            android:textSize="15sp" />

        <FrameLayout
            android:id="@+id/flFork"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/dp_10"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true">
            
            <ImageView
                android:layout_width="13dp"
                android:layout_height="13dp"
                android:src="@mipmap/icon_black_fork"
                android:contentDescription="关闭"/>
                <!--icon_black_fork,这是在android studio系统中添加资源图标-->

        </FrameLayout>
    </RelativeLayout>
	<!--<color name="veeeeee">#eeeeee</color>-->
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="@color/veeeeee" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

    <LinearLayout
        android:id="@+id/ll_dialog_confirm"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_margin="@dimen/dp_5"
        android:visibility="gone"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">

        <FrameLayout
            android:id="@+id/fl_dialog_close"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="?android:attr/selectableItemBackground">

            <TextView
                android:id="@+id/tv_dialog_confirm"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#C0C0C0"
                android:gravity="center"
                android:text="@string/confirm"
                android:textSize="16sp"
                android:textColor="#000000"/>
        </FrameLayout>
    </LinearLayout>
</LinearLayout>

3、实现视图

从底部弹出列表对话框(单选/多选)功能,单选或多选确定后通知观察者MainActivity.kt

package com.example.myapplication3

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication3.data.Dict
import com.example.myapplication3.util.OnResultCallback
import com.example.myapplication3.util.showMCListDialog
import com.example.myapplication3.util.showRadioListDialog
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private var list: MutableList<Dict> = ArrayList()
    private var index: Int = 0

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

    private fun initView() {
        textView1.text = "测试1"//默认
        textView2.text = "测试1"//默认
    }

    private fun initDatas() {
        for (i in 1..10) {
            val sc = Dict("测试$i", "$i")
            list.add(sc)
        }
    }

    private fun initListener() {

        //从底部弹出列表对话框(单选)
        textView1.setOnClickListener {
            for (i in 0 until list.size) {
                if (textView1.text == list[i].dataName) {
                    index = i;
                    break
                }
            }
            showRadioListDialog(
                textView1.text.toString(),
                list[index].dataValue,
                list as List<Dict>,
                object : OnResultCallback<String> {
                    override fun onResult(dataName: String) {
                        textView1.text = dataName
                    }
                })
        }

        //从底部弹出列表对话框(多选)
        textView2.setOnClickListener {
            for (i in 0 until list.size) {
                if (textView1.text == list[i].dataName) {
                    index = i;
                    break
                }
            }
            showMCListDialog(
                textView1.text.toString(),
                list[index].dataValue,
                list as List<Dict>,
                object : OnResultCallback<String> {
                    override fun onResult(s: String) {
                        textView2.text = s
                    }
                })
        }
    }
}

activity_main.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="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#DBDCDD"
        android:textSize="30dp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="50dp"/>

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#DBDCDD"
        android:textSize="30dp" />
</LinearLayout>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彬sir哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值