You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建可全局复用的Android BottomSheet展示组件?

Android 全局复用BottomSheetDialogFragment实现方案

核心实现思路

通过「基类封装通用样式 + 单例管理类统一调度」的方式,把所有BottomSheet的创建、展示、回调逻辑收敛到同一个类中,页面仅需一行代码即可调用,不需要单独编写弹窗逻辑。

具体实现步骤

1. 封装通用BaseBottomSheet基类

先抽象所有弹窗的公共配置,避免每个子类重复写样式代码:

open class BaseBottomSheetDialogFragment : BottomSheetDialogFragment() {
    // 统一配置默认样式,可按需覆盖
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
        dialog.behavior.apply {
            state = BottomSheetBehavior.STATE_EXPANDED
            isDraggable = false // 按需配置是否允许拖拽关闭
            skipCollapsed = true
        }
        // 设置统一圆角背景
        dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        return dialog
    }

    // 统一回调接口,也可以用函数类型参数代替
    interface OnBottomSheetActionListener {
        fun onConfirm(data: Bundle? = null)
        fun onCancel()
    }
}

2. 实现业务弹窗子类

分别为你的两个弹窗实现对应的Fragment,仅写业务相关的布局和交互:

关闭确认弹窗

class CloseBottomSheet : BaseBottomSheetDialogFragment() {
    private var actionListener: OnBottomSheetActionListener? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bottom_sheet_close, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 确认按钮点击
        view.findViewById<Button>(R.id.btn_confirm).setOnClickListener {
            actionListener?.onConfirm()
            dismiss()
        }
        // 取消按钮点击
        view.findViewById<Button>(R.id.btn_cancel).setOnClickListener {
            actionListener?.onCancel()
            dismiss()
        }
    }

    fun setActionListener(listener: OnBottomSheetActionListener) {
        this.actionListener = listener
    }

    companion object {
        fun newInstance() = CloseBottomSheet()
    }
}

登出确认弹窗

class LogoutConfirmBottomSheet : BaseBottomSheetDialogFragment() {
    private var actionListener: OnBottomSheetActionListener? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.bottom_sheet_logout_confirm, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.btn_logout).setOnClickListener {
            actionListener?.onConfirm()
            dismiss()
        }
        view.findViewById<Button>(R.id.btn_cancel).setOnClickListener {
            actionListener?.onCancel()
            dismiss()
        }
    }

    fun setActionListener(listener: OnBottomSheetActionListener) {
        this.actionListener = listener
    }

    companion object {
        fun newInstance() = LogoutConfirmBottomSheet()
    }
}

3. 实现全局统一调度管理类

用单例类BottomSheetManager收敛所有弹窗的调用逻辑,外部不需要知道具体Fragment的实现:

// 先定义弹窗类型枚举
enum class BottomSheetType {
    CLOSE_CONFIRM,
    LOGOUT_CONFIRM
}

object BottomSheetManager {
    fun show(
        activity: FragmentActivity,
        type: BottomSheetType,
        listener: BaseBottomSheetDialogFragment.OnBottomSheetActionListener
    ) {
        val fragment = when (type) {
            BottomSheetType.CLOSE_CONFIRM -> CloseBottomSheet.newInstance()
            BottomSheetType.LOGOUT_CONFIRM -> LogoutConfirmBottomSheet.newInstance()
        }
        fragment.setActionListener(listener)
        fragment.show(activity.supportFragmentManager, fragment::class.simpleName)
    }

    // 兼容在Fragment中调用的重载方法
    fun show(
        fragment: Fragment,
        type: BottomSheetType,
        listener: BaseBottomSheetDialogFragment.OnBottomSheetActionListener
    ) {
        val bottomSheet = when (type) {
            BottomSheetType.CLOSE_CONFIRM -> CloseBottomSheet.newInstance()
            BottomSheetType.LOGOUT_CONFIRM -> LogoutConfirmBottomSheet.newInstance()
        }
        bottomSheet.setActionListener(listener)
        bottomSheet.show(fragment.childFragmentManager, bottomSheet::class.simpleName)
    }
}

4. 页面调用示例

任意Activity/Fragment需要展示弹窗时,仅需一行代码调用即可:

// Activity中调用登出弹窗
BottomSheetManager.show(
    this,
    BottomSheetType.LOGOUT_CONFIRM,
    object : BaseBottomSheetDialogFragment.OnBottomSheetActionListener {
        override fun onConfirm(data: Bundle?) {
            // 处理登出逻辑
        }

        override fun onCancel() {
            // 可选处理取消逻辑
        }
    }
)

// Fragment中调用关闭弹窗
BottomSheetManager.show(
    this,
    BottomSheetType.CLOSE_CONFIRM,
    object : BaseBottomSheetDialogFragment.OnBottomSheetActionListener {
        override fun onConfirm(data: Bundle?) {
            // 处理关闭页面逻辑
        }

        override fun onCancel() {}
    }
)

注意事项

  • 禁止传入Application Context调用,必须依赖Activity/Fragment实例获取FragmentManager,否则会抛出异常
  • 如果需要给弹窗传递自定义参数,可以在show方法中添加可选Bundle参数,创建Fragment时通过setArguments传入即可
  • 回调实例建议和页面生命周期绑定,避免内存泄漏,页面销毁时弹窗会自动跟随销毁,无需额外处理

内容的提问来源于stack exchange,提问作者JuJu Juned

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:06:03