You need to enable JavaScript to run this app. 通过Fragment导航返回后Snackbar重叠Floating Action Button如何解决
优惠活动
大模型
产品
解决方案
定价
更多

通过Fragment导航返回后Snackbar重叠Floating Action Button如何解决

问题根因

你当前代码的问题在于Snackbar的宿主视图选择错误:你在UpdateFragment中调用createSnackBar时传入的是UpdateFragment自身的根视图requireView(),Snackbar会顺着该视图向上查找最外层根布局作为附着节点,随后你立即执行导航操作,UpdateFragment的视图被销毁,Snackbar最终直接附着到Activity的Window DecorView上,和ListFragment里的CoordinatorLayout不存在从属关系,CoordinatorLayout感知不到该Snackbar的存在,自然不会触发Floating Action Button(以下简称FAB)的上移动画,导致重叠。

异常效果与预期效果对比如下:

  • 当前异常效果:当前异常效果
  • 预期正常效果:预期正常效果
可行解决方案

以下方案按推荐优先级排序:

方案1:Fragment结果回传,由ListFragment触发Snackbar(最推荐)

将操作成功的事件回传给ListFragment,由ListFragment使用自身内部的CoordinatorLayout作为Snackbar的宿主视图,此时CoordinatorLayout可正常识别Snackbar,自动触发FAB偏移。

代码实现

  1. UpdateFragment操作成功后,先发送结果再执行导航:
// UpdateFragment 操作成功后逻辑
setFragmentResult("operation_success", bundleOf("msg_res" to R.string.successfully_updated))
findNavController().navigate(R.id.action_updateFragment_to_listFragment)
  1. ListFragment的onViewCreated中注册结果监听器,接收事件后创建Snackbar:
// ListFragment onViewCreated 中添加
setFragmentResultListener("operation_success") { _, bundle ->
    val messageRes = bundle.getInt("msg_res")
    // 传入ListFragment布局中的CoordinatorLayout实例作为宿主
    createSnackBar(binding.coordinatorLayout, messageRes, Snackbar.LENGTH_SHORT)
}

方案2:直接指定CoordinatorLayout作为Snackbar宿主

如果你的CoordinatorLayout和FAB都定义在Activity层级,可直接传入Activity中的CoordinatorLayout作为Snackbar的宿主:

// UpdateFragment 操作成功后逻辑
val activityCoordinator = requireActivity().findViewById<CoordinatorLayout>(R.id.activity_coordinator_id)
createSnackBar(activityCoordinator, R.string.successfully_updated, Snackbar.LENGTH_SHORT)
findNavController().navigate(R.id.action_updateFragment_to_listFragment)

方案3:手动控制FAB偏移(兜底方案)

如果以上方案都不适用,可通过Snackbar的展示/销毁回调手动控制FAB的位置:

改造createSnackBar函数:

fun createSnackBar(view: View, @StringRes message: Int, duration: Int, fab: FloatingActionButton? = null) {
    val resources = view.resources
    val snackBar = Snackbar.make(view, resources.getString(message), duration)
    fab?.let { targetFab ->
        snackBar.addCallback(object : Snackbar.Callback() {
            override fun onShown(sb: Snackbar?) {
                super.onShown(sb)
                sb?.view?.height?.let { height ->
                    targetFab.animate().translationY(-height.toFloat()).setDuration(200).start()
                }
            }

            override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                super.onDismissed(transientBottomBar, event)
                targetFab.animate().translationY(0f).setDuration(200).start()
            }
        })
    }
    snackBar.show()
}

调用时传入FAB实例即可:

// ListFragment中调用时传入自身的FAB实例
createSnackBar(requireView(), R.string.successfully_updated, Snackbar.LENGTH_SHORT, binding.fab)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 18:06:04