当前位置: 首页 > news >正文

(Kotlin) Android使用DialogX实现iOS风格底部弹窗(带Toggle开关)

本文将详细介绍如何使用DialogX库实现一个iOS风格的底部弹窗,包含图标文本Toggle开关的列表项。
实现步骤
1. 添加依赖
build.gradle文件中添加:

implementation 'com.github.kongzue.DialogX:DialogX:0.0.49.beta14'
implementation 'com.github.kongzue.DialogX:DialogXIOSStyle:0.0.49.beta14'
implementation 'androidx.recyclerview:recyclerview:1.3.2'

2. 创建布局文件
底部弹窗主布局 (dialog_bottom_toggle.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/bg_bottom_dialog_round_top">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textSize="18sp"
        android:textStyle="bold"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxHeight="400dp"/>

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:text="取消"
        android:background="?attr/selectableItemBackground"/>
</LinearLayout>

列表项布局 (item_toggle.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:orientation="horizontal"
    android:paddingStart="24dp"
    android:paddingEnd="16dp"
    android:gravity="center_vertical">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginEnd="16dp"/>

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textSize="16sp"/>

    <androidx.appcompat.widget.SwitchCompat
        android:id="@+id/switch_toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

3. 实现工具类

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.widget.SwitchCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.kongzue.dialogx.dialogs.CustomDialog
import com.kongzue.dialogx.interfaces.OnBindView
import com.kongzue.dialogx.style.IOSStyle
import smartconnection.com.smartconnect.R

object BottomToggleDialog {

    data class ToggleItem(
        val iconRes: Int,
        val title: String,
        var isChecked: Boolean = false,
        val onToggleChanged: ((Boolean) -> Unit)? = null
    )

    /**
     * 使用CustomDialog的可靠实现
     */
    fun show(
        context: Context,
        title: String? = null,
        items: List<ToggleItem>
    ) {
        CustomDialog.build()
            .setCustomView(object : OnBindView<CustomDialog>(R.layout.dialog_bottom_toggle) {
                override fun onBind(dialog: CustomDialog?, view: View?) {
                    view?.apply {
                        // 绑定视图
                        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
                        val tvTitle = findViewById<TextView>(R.id.tv_title)
                        val btnCancel = findViewById<Button>(R.id.btn_cancel)

                        // 设置标题
                        title?.let { tvTitle.text = it } ?: run { tvTitle.visibility = View.GONE }

                        // 配置列表
                        recyclerView.layoutManager = LinearLayoutManager(context)
                        recyclerView.adapter = ToggleAdapter(items).apply {
                            onItemClick = { position, isChecked ->
                                items[position].isChecked = isChecked
                                items[position].onToggleChanged?.invoke(isChecked)
                            }
                        }

                        // 取消按钮
                        btnCancel.setOnClickListener { dialog?.dismiss() }
                    }
                }
            })
            .setStyle(IOSStyle.style())
            .setAlign(CustomDialog.ALIGN.BOTTOM)
            .setCancelable(true)
            .show()
    }

    private class ToggleAdapter(private val items: List<ToggleItem>) :
        RecyclerView.Adapter<ToggleAdapter.ViewHolder>() {

        var onItemClick: ((Int, Boolean) -> Unit)? = null

        class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val ivIcon: ImageView = view.findViewById(R.id.iv_icon)
            val tvTitle: TextView = view.findViewById(R.id.tv_title)
            val switch: SwitchCompat = view.findViewById(R.id.switch_toggle)
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_toggle, parent, false)
            return ViewHolder(view)
        }

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = items[position]
            holder.ivIcon.setImageResource(item.iconRes)
            holder.tvTitle.text = item.title
            holder.switch.isChecked = item.isChecked

            holder.switch.setOnCheckedChangeListener { _, isChecked ->
                onItemClick?.invoke(position, isChecked)
            }

            holder.itemView.setOnClickListener {
                holder.switch.toggle()
            }
        }

        override fun getItemCount() = items.size
    }
}

使用示例

// 准备数据
val items = listOf(
    BottomToggleDialog.ToggleItem(
        iconRes = R.drawable.ic_notification,
        title = "消息通知",
        isChecked = true
    ) { isChecked ->
        Toast.makeText(this, "通知状态: $isChecked", Toast.LENGTH_SHORT).show()
    },
    BottomToggleDialog.ToggleItem(
        iconRes = R.drawable.ic_dark_mode,
        title = "暗黑模式",
        isChecked = false
    ) { isChecked ->
        Toast.makeText(this, "暗黑模式: $isChecked", Toast.LENGTH_SHORT).show()
    }
)

// 显示弹窗
BottomToggleDialog.show(
    context = this,
    title = "功能设置",
    items = items
)

关键点说明
1.底部显示控制:

setAlignBottom() 确保内容对齐底部

自定义动画实现滑动效果

顶部圆角背景优化视觉效果

2.数据绑定:

使用RecyclerView实现高效列表

通过回调处理Toggle状态变化

http://www.dtcms.com/a/106825.html

相关文章:

  • 算法与数据结构面试题
  • 【硬件视界8】电源供应器(PSU):计算机的“心脏“
  • 洛谷题单3-P5720 【深基4.例4】一尺之棰-python-流程图重构
  • Tomcat 部署 Jenkins.war 详细教程(含常见问题解决)
  • 存储型XSS漏洞解析
  • springBoot统一响应类型3.5.2版本
  • 【橘子大模型】关于PromptTemplate
  • 定制化管理系统与通用管理系统,谁更胜一筹?
  • MySQL的进阶语法7(索引-B+Tree 、Hash、聚集索引 、二级索引(回表查询)、索引的使用及设计原则
  • ES6对函数参数的新设计
  • 贪心算法,其优缺点是什么?
  • 第二篇:系统分析师——1-6章
  • 深入解析 Spring Boot 测试核心注解
  • 使用UDP建立连接,会存在什么问题?
  • es使用ik分词器并自定义中文词库实现热更新
  • 软件工程13 条法则
  • 空调开机启动后发出噼里啪啦的异响分析与解决
  • C语言--字符串逆序
  • Timer的底层实现原理?
  • LETTERS(DFS)
  • Java 递归全解析:从原理到优化的实战指南
  • Elasticsearch 正排索引
  • 内网环境将nginx的http改完https访问
  • Sentinel-自定义资源实现流控和异常处理
  • Spring事务的传播机制
  • 二叉树的ACM板子(自用)
  • 网管平台核心功能解析(七)——IP管理
  • 【Neo4j介绍】
  • web网页上实现录音功能(vue3)
  • 大模型加速器2.0:构建智能知识库,助力大模型减少“幻觉”