如何使BottomSheet扩展至Toolbar底部而非其下方?兼Snackbar问题
解决BottomSheet扩展高度限制及Snackbar兼容问题
我来帮你搞定这两个问题,不用手动计算设备高度那么麻烦,用CoordinatorLayout的特性就能优雅解决:
一、限制BottomSheet扩展至Toolbar底部
你现在设置layout_height="match_parent"导致BottomSheet顶到Toolbar下方(屏幕顶部),其实可以通过两种方式控制扩展状态的最大高度:
方案1:自定义BottomSheetBehavior(推荐)
创建一个继承自BottomSheetBehavior的类,重写方法来限制扩展高度,适配所有屏幕尺寸:
class CustomBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet) : BottomSheetBehavior<V>(context, attrs) { private var toolbarHeight = 0 override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean { // 获取Toolbar的高度(替换成你项目中Toolbar的id) val toolbar = parent.findViewById<Toolbar>(R.id.toolbar) toolbarHeight = toolbar.height return super.onLayoutChild(parent, child, layoutDirection) } override fun calculateHeight(parent: CoordinatorLayout, child: V): Int { // 扩展状态下的高度 = 父容器高度 - Toolbar高度 return parent.height - toolbarHeight } }
然后在布局中给BottomSheet布局指定这个自定义Behavior:
<LinearLayout android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="com.yourpackage.CustomBottomSheetBehavior" ...>
方案2:代码动态设置高度(简单直接)
如果不想自定义Behavior,也可以在代码中监听Toolbar布局完成后,动态调整BottomSheet的高度:
val toolbar = findViewById<Toolbar>(R.id.toolbar) val bottomSheet = findViewById<LinearLayout>(R.id.bottom_sheet) val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet) // 等待Toolbar布局完成,避免获取到高度为0 toolbar.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { toolbar.viewTreeObserver.removeOnGlobalLayoutListener(this) // 设置扩展状态的偏移量,让BottomSheet停在Toolbar底部 bottomSheetBehavior.expandedOffset = toolbar.height // 或者直接设置BottomSheet的布局高度 bottomSheet.layoutParams.height = resources.displayMetrics.heightPixels - toolbar.height bottomSheet.requestLayout() } })
二、解决BottomSheet与Snackbar的兼容问题
Snackbar默认会和BottomSheet重叠,你可以通过两种方式处理:
- 让Snackbar显示在BottomSheet上方:给Snackbar设置锚点为BottomSheet,这样它会自动贴在BottomSheet顶部:
Snackbar.make(findViewById(R.id.coordinator_layout), "提示内容", Snackbar.LENGTH_SHORT) .setAnchorView(R.id.bottom_sheet) .show()
- 让BottomSheet自动上移避让Snackbar:在自定义的
CustomBottomSheetBehavior中添加以下方法,监听Snackbar的出现并调整BottomSheet位置:
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean { return dependency is Snackbar.SnackbarLayout } override fun onDependentViewChanged(parent: CoordinatorLayout, child: V, dependency: View): Boolean { val snackbarHeight = dependency.height // 调整BottomSheet的peek高度,避免被Snackbar遮挡 this.peekHeight = snackbarHeight return super.onDependentViewChanged(parent, child, dependency) }
这样就能同时解决两个问题,不用手动计算设备高度,适配性更强~
内容的提问来源于stack exchange,提问作者I.S
相关产品推荐
相关产品推荐

