本文将详细介绍如何使用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"><TextViewandroid: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.RecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="wrap_content"android:maxHeight="400dp"/><Buttonandroid: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"><ImageViewandroid:id="@+id/iv_icon"android:layout_width="24dp"android:layout_height="24dp"android:layout_marginEnd="16dp"/><TextViewandroid:id="@+id/tv_title"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textSize="16sp"/><androidx.appcompat.widget.SwitchCompatandroid: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.Robject 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 = isCheckeditems[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)? = nullclass 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.titleholder.switch.isChecked = item.isCheckedholder.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状态变化