如何固定 Snackbar 的高度和位置?
Posted
技术标签:
【中文标题】如何固定 Snackbar 的高度和位置?【英文标题】:How to fix the Snackbar height and position? 【发布时间】:2017-05-09 03:06:27 【问题描述】:在 Android 支持库 24.1.1 上,Snackbar 工作正常:
然后从 Android 支持库 24.2.0 开始,Snackbar 开始表现如下:
在库revision history上,有如下声明:
行为变化:如果状态栏是半透明的,Snackbar 现在会绘制在导航栏后面。
但问题是我的应用是全屏的,没有导航栏或状态栏。我该如何解决?
【问题讨论】:
您可以使用自定义布局! ***.com/questions/32453946/… 你能放一些代码吗?我所说的代码是指这个活动的布局,你所有的小吃店代码和你的 Gradle 配置。 【参考方案1】:我最近通过从 Snackbar 视图的底部边缘减去导航栏高度解决了这个问题。
首先我们需要导航栏的高度。我在此处标记为正确的答案中找到了代码: How to REALLY get the navigation bar height in android
接下来,使用以下代码调整 Snackbar 底部边距:
final Snackbar snackbar = Snackbar.make(findViewById(R.id.fullscreen_content),
message, Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
// Adjust Snackbar height for fullscreen immersive mode
int navbarHeight = getNavigationBarSize(this).y;
CoordinatorLayout.LayoutParams parentParams = (CoordinatorLayout.LayoutParams) snackbarView.getLayoutParams();
parentParams.setMargins(0, 0, 0, 0 - navbarHeight);
snackbarView.setLayoutParams(parentParams);
snackbar.show();
请注意,我使用了 CoordinatorLayout 的 LayoutParams。您应该将 CoordinatorLayout 替换为您传递给 Snackbar.make()
函数的任何父布局类型(在我的情况下,R.id.fullscreen_content
是 CoordinatorLayout)。使用 CoordinatorLayout 的好处是它允许通过滑动作为标准行为来消除 Snackbars。
【讨论】:
You should replace CoordinatorLayout with whichever parent layout type you have passed in to your Snackbar.make() function
当你只想编辑边距时,你也可以只使用公共父 MarginLayoutParams【参考方案2】:
现在是 2020 年,我也不知道这是否相关,但在使用 android 10 手势导航时,我的快餐栏底部有一些填充。以上都不适用于我的情况。我终于用一条超级简单的线解决了它:
val snackbar = Snackbar.make(view, message, duration)
snackbar.isGestureInsetBottomIgnored = true // here
snackbar.show()
希望对你有帮助。
【讨论】:
是的!这解决了我的问题 - 对于 Java,它只是 setIsGestureInsetBottomIgnored(true); 太棒了!这正是我想要的!【参考方案3】:接受的答案适用于旧版本的支持库,其中 Snackbar
只是一个矩形视图。通过将边距更改为负值实际发生的情况只是切断了SnackbarLayout
(Snackbar
的容器布局)的底部,因此Snackbar
具有圆角的较新版本在此解决方案中看起来很糟糕。
线索在这里的代码中:https://github.com/material-components/material-components-android/blob/cd59e98f7e2185ddb075ff0fc91f29765d562968/lib/java/com/google/android/material/snackbar/BaseTransientBottomBar.java#L272
实际发生的是向容器添加了填充,因此正确修复高度的方法是将填充重置为正确的数量。您可以通过添加额外的OnApplyWindowInsetsListener
来做到这一点,如下所示(将底部填充设置为与顶部相同会使Snackbar
看起来正常):
ViewCompat.setOnApplyWindowInsetsListener(snackbar.view) v, insets ->
v.setPadding(v.paddingLeft, v.paddingTop, v.paddingRight, v.paddingTop)
insets
然后,由于 Snackbar
现在将是正确的高度,但出现在半透明导航栏后面,您可以将底部边距增加底部插图的值:
ViewCompat.setOnApplyWindowInsetsListener(view) v, insets ->
v.setPadding(v.paddingLeft, v.paddingTop, v.paddingRight, v.paddingTop)
val params = v.layoutParams as ViewGroup.MarginLayoutParams
params.updateMargins(
params.leftMargin,
params.topMargin,
params.rightMargin,
params.bottomMargin + insets.systemWindowInsetBottom
)
v.layoutParams = params
insets
这实际上已在 Material 1.1.0 alpha 库中得到修复(该库现在更改边距而不是填充),但它们可能还没有准备好用于生产。
【讨论】:
【参考方案4】:看看这个答案https://***.com/a/42180120/2550743然后替换
params.setMargins(params.leftMargin,
params.topMargin,
params.rightMargin,
params.bottomMargin + ScreenUtils.getNavigationBarHeight(activity));
到
params.setMargins(params.leftMargin,
params.topMargin,
params.rightMargin,
params.bottomMargin - ScreenUtils.getNavigationBarHeight(activity));
【讨论】:
【参考方案5】:另一种方法是
Snackbar snackbar = Snackbar.make(view, ...);
View snackBarView = snackbar.getView();
ViewCompat.setFitsSystemWindows(snackBarView, false);
ViewCompat.setOnApplyWindowInsetsListener(snackBarView, null);
这将在沉浸式模式中禁用额外的底部填充。
【讨论】:
它对我不起作用。除此之外,ViewCompat.setFitsSystemWindows
已被贬低。
谢谢,它有效!我改变了一点代码 ViewsnackbarView =snackbar.getView(); snapbarView.setFitsSystemWindows(false); snapbarView.setOnApplyWindowInsetsListener(null);【参考方案6】:
在您的小吃店中使用它,
FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.BOTTOM;
【讨论】:
你用过view.requestLayout();在这行之后?【参考方案7】:如果您只关心身高而不是位置,那么请准备好让您大吃一惊! :D
将您的小吃店内容设置为:
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'Your SnackBar message',
),
SizedBox(
height: 70, // Your desired height
)
],
))
【讨论】:
以上是关于如何固定 Snackbar 的高度和位置?的主要内容,如果未能解决你的问题,请参考以下文章