如何修复Snackbar的高度和位置?

thi*_*olr 6 android android-support-library android-design-library android-snackbar

Android支持库24.1.1上,Snackbar工作正常:

之前

然后从Android支持库24.2.0开始,Snackbar开始表现如下:

后

在库修订历史记录中,有以下语句:

行为更改:如果状态栏是半透明的,Snackbar现在会在导航栏后面绘制.

但问题是我的应用程序是全屏的,它没有导航栏或状态栏.我该如何解决?

小智 8

我最近通过从Snackbar视图的底部边缘减去导航栏高度来解决这个问题.

首先我们需要导航栏高度.我在答案中找到了代码,在此标记为正确: 如何在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();
Run Code Online (Sandbox Code Playgroud)

请注意,我使用了CoordinatorLayout的LayoutParams.您应该将CoordinatorLayout替换为您传递给Snackbar.make()函数的父布局类型(在我的情况下,R.id.fullscreen_content是CoordinatorLayout).使用CoordinatorLayout的好处是它允许通过滑动作为标准行为来解散Snackbars.


Phi*_*lio 6

接受的答案适用于旧版本的支持库,其中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
}
Run Code Online (Sandbox Code Playgroud)

然后,由于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
}
Run Code Online (Sandbox Code Playgroud)

这实际上已在 Material 1.1.0 alpha 库中修复(该库现在更改边距而不是填充),但它们可能尚未准备好用于生产。


小智 5

看看这个答案/sf/answers/2952608431/并替换

 params.setMargins(params.leftMargin,
            params.topMargin,
            params.rightMargin,
            params.bottomMargin + ScreenUtils.getNavigationBarHeight(activity));
Run Code Online (Sandbox Code Playgroud)

 params.setMargins(params.leftMargin,
            params.topMargin,
            params.rightMargin,
            params.bottomMargin - ScreenUtils.getNavigationBarHeight(activity));
Run Code Online (Sandbox Code Playgroud)


小智 5

现在是 2020 年,我也不知道它是否相关,但是在使用 android 10 手势导航时,我的快餐栏底部有一些填充。以上都不适用于我的情况。我终于用超级简单的一行修复了它:

val snackbar = Snackbar.make(view, message, duration)
snackbar.isGestureInsetBottomIgnored = true // here
snackbar.show()
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。