设置Snackbar锚点为adContainer后FAB无法浮动的解决方法
解决Snackbar锚定到adContainer时FAB不联动的问题
这个问题我之前也碰到过!当把Snackbar锚定到自定义容器后,FAB的默认行为就“失灵”了——它只认直接锚定在CoordinatorLayout底部的Snackbar,完全不理会锚定到其他View的Snackbar。咱们来一步步解决它:
问题根源
默认的FloatingActionButton.Behavior只会监听以CoordinatorLayout底部为锚点的Snackbar。当你把Snackbar的锚点设为adContainer后,Snackbar的位置计算基准变成了这个底部容器,而不是CoordinatorLayout的底部,所以FAB的Behavior检测不到Snackbar的显示/隐藏,自然不会跟着移动。
解决方案:自定义FAB的Behavior
我们可以给FAB写一个自定义Behavior,让它能识别锚定到adContainer的Snackbar,并响应其位置变化。
1. 创建自定义Behavior类
import android.content.Context import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.snackbar.Snackbar class AnchorAwareFabBehavior(context: Context, attrs: AttributeSet) : FloatingActionButton.Behavior(context, attrs) { override fun layoutDependsOn(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View): Boolean { // 让FAB既依赖默认的Snackbar,也依赖锚定到adContainer的Snackbar return super.layoutDependsOn(parent, child, dependency) || (dependency is Snackbar.SnackbarLayout && (dependency.layoutParams as? CoordinatorLayout.LayoutParams)?.anchorId == R.id.adContainer) } override fun onDependentViewChanged(parent: CoordinatorLayout, child: FloatingActionButton, dependency: View): Boolean { val defaultResult = super.onDependentViewChanged(parent, child, dependency) if (dependency is Snackbar.SnackbarLayout) { // 计算Snackbar的高度,调整FAB的Y轴偏移量 val fabParams = child.layoutParams as CoordinatorLayout.LayoutParams val bottomMargin = fabParams.bottomMargin val snackbarHeight = dependency.height child.translationY = -(snackbarHeight + bottomMargin).toFloat() } return defaultResult } }
2. 在XML中给FAB设置这个Behavior
把FAB的app:layout_behavior属性替换成你刚才创建的自定义Behavior(注意替换成你的实际包名):
<com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/floatingActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_marginBottom="96dp" android:layout_marginEnd="32dp" android:clickable="true" android:focusable="true" app:layout_behavior="com.yourpackage.AnchorAwareFabBehavior" <!-- 替换为你的实际包名 --> app:srcCompat="@android:drawable/ic_input_add" />
3. 保持原有的Snackbar代码不变
你原来的Snackbar初始化代码不需要修改,直接用就行:
val snackbar = Snackbar.make(main_content, "Item Deleted", Snackbar.LENGTH_INDEFINITE) snackbar.anchorView = adContainer snackbar.setAction("Dismiss"){ } snackbar.show()
为什么你之前修改bottomMargin无效?
当给Snackbar设置了anchorView后,Snackbar的位置由锚点View的布局规则控制,此时手动设置bottomMargin会被锚点的布局逻辑覆盖,所以不会生效。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

