如何固定 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 只是一个矩形视图。通过将边距更改为负值实际发生的情况只是切断了SnackbarLayoutSnackbar 的容器布局)的底部,因此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 的高度和位置?的主要内容,如果未能解决你的问题,请参考以下文章

Snackbar 的高度自定义

怎么做固定高度的滚动条???

Flutter SnackBar 的高度

棒棒糖前设备中的 Snackbar 高度太大

在 SnackBar 上包装内容高度

HTML 位置:固定可变高度页眉和页内锚点