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

时间:2016-12-23 11:48:26

标签: android android-support-library android-design-library android-snackbar

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

before

然后从 Android支持库24.2.0 开始,Snackbar开始表现得像这样:

after

在库revision history上,有以下声明:

  

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

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

7 个答案:

答案 0 :(得分:7)

我最近通过从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。

答案 1 :(得分:4)

查看此答案https://stackoverflow.com/a/42180120/2550743,然后替换

 params.setMargins(params.leftMargin,
            params.topMargin,
            params.rightMargin,
            params.bottomMargin - ScreenUtils.getNavigationBarHeight(activity));

QT_WEBKIT_LOG

答案 2 :(得分:3)

现在是2020年,我也不知道是否相关,但是在使用android 10手势导航时,我的便餐栏的底部有一些填充。以上都不适合我的情况。我终于用一条超简单的线解决了这个问题:

val snackbar = Snackbar.make(view, message, duration)
snackbar.isGestureInsetBottomIgnored = true // here
snackbar.show()

希望有帮助。

答案 3 :(得分:1)

可接受的答案适用于旧版本的支持库,其中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 :(得分:1)

另一种方式是

Snackbar snackbar = Snackbar.make(view, ...);
View snackBarView = snackbar.getView();

ViewCompat.setFitsSystemWindows(snackBarView, false);
ViewCompat.setOnApplyWindowInsetsListener(snackBarView, null);

这将在沉浸模式下禁用额外的底部填充。

答案 5 :(得分:0)

在小吃店中使用它,

FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
    params.gravity = Gravity.BOTTOM;

答案 6 :(得分:0)

如果您只关心身高而不是身高,那么请准备好让自己震惊! :D

将快餐栏内容设置为:

Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(
            'Your SnackBar message',
          ),
          SizedBox(
            height: 70, // Your desired height
          )
        ],
      ))