给Snackbar视图添加边距

28

我正在更新我的应用程序以使用snackbars,根据Google规范,它们可以以不同的方式使用。http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs

示例A:

带有边距的Snackbar

示例B:

固定在布局中的Snackbar

这是目前我的代码:

Snackbar snackbar = Snackbar.make(mParentLayout, displayMessage,     
    Snackbar.LENGTH_LONG);
    snackbar.setAction(actionMessage, mClickListener);
    snackbar.show();

我在示例B中得到了结果,

如何添加边距?

20个回答

29

除了Saeid的答案之外,您还可以获取默认的SnackBar布局参数并根据需要进行修改:

public static void displaySnackBarWithBottomMargin(Snackbar snackbar, int sideMargin, int marginBottom) {
    final View snackBarView = snackbar.getView();
    final CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) snackBarView.getLayoutParams();

    params.setMargins(params.leftMargin + sideMargin,
                params.topMargin,
                params.rightMargin + sideMargin,
                params.bottomMargin + marginBottom);

    snackBarView.setLayoutParams(params);
    snackbar.show();
}

18
谢谢。我的小建议是使用以下代码: final ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) snackBarView.getLayoutParams(); 这将使代码更加通用,因为它适用于大多数布局。 - lionscribe
3
这段代码对我不起作用,只需添加一个黑色边距即可。 - Fereshteh Naji
@FereshtehNaji 你可以查看我的答案。它百分之百有效。 - M.Usman
这对我也没有影响。 - lostintranslation

24

以上的解决方案都对我没用。

但我有一个小技巧,可以借助翻译来实现。

Snackbar snackbar = Snackbar.make(mActivity.getWindow().getDecorView().getRootView(), message, Snackbar.LENGTH_SHORT);
View snackBarView = snackbar.getView();
snackBarView.setTranslationY(-(convertDpToPixel(48, mActivity)));
snackbar.show();

在这里你可以找到convertDpToPixel方法的链接


2
不幸的是,在我的情况下,snackbar.getView().setTranslationY() 没有任何作用,而 snackbar.getView().setTranslationX() 则按预期工作。 - Hong
1
帮了我大忙。我猜这是其中一种优雅的解决方案!谢谢。 - Georgiy Chebotarev
这是唯一适用于所有设备的方法。当您为Snackbar使用自定义布局时,这种方法尤其有用。 - CalmPerson

16
使用 Material Components 库,您可以在应用程序主题中使用 snackbarStyle 属性:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
    <item name="snackbarStyle">@style/MySnackbar</item>
</style>

随着:

<style name="MySnackbar" parent="Widget.MaterialComponents.Snackbar">
    <item name="android:layout_margin">32dp</item>
</style>

在此输入图片描述


1
你如何在程序中将这种样式应用到Snackbar? - Umang Kothari
它将默认应用于每个 Snackbar,因为主题是 AppTheme,这是 menifest 中 <Application> 标签上的默认主题。 - Mitul Varmora
@UmangKothari 是的,借助ContextThemeWrapper的帮助,我们可以创建一个具有所需SnackBar样式的上下文并将其提供给SnackBar.make()函数。 SnackBar将自动配置自己。更多信息在这里:https://ataulm.com/2019/11/20/using-context-theme-wrapper.html - Paukdcn
1
layout_marginStart、layout_marginLeft、layout_marginHorizontal等属性无效。似乎只有layout_margin属性有效。 - mazend

9
我只是添加我的解决方案,因为@BamsMamx的解决方案没有起作用,我需要添加getChildAt(0)
  public static void displaySnackBarWithBottomMargin(BaseActivity activity, View main) {
   Snackbar snackbar = Snackbar.make(main, R.string.register_contacts_snackbar, Snackbar.LENGTH_SHORT);
    final FrameLayout snackBarView = (FrameLayout) snackbar.getView();

    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) snackBarView.getChildAt(0).getLayoutParams();
    params.setMargins(params.leftMargin,
                params.topMargin,
                params.rightMargin,
                params.bottomMargin + 100;
    snackBarView.getChildAt(0).setLayoutParams(params);
    snackbar.show();
}

谢谢。这是唯一一个在我的情况下有效的。我尝试了其他的。右边距似乎不起作用,但底部和左边距可以使用。 - Hong
@BamsMamx的解决方案曾经可行,但目前你的版本是有效的 :) 我猜Snackbar实现中有些变化。 - algrid

8

在我的情况下,添加CoordinatorLayout或FrameLayout并设置边距无效。

为了解决这个问题,使用Drawable背景,其中使用item设置边距,使用shape设置所需的填充。

container_snackbar.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!--    Set Margin Here -->
    <item
        android:left="20dp"
        android:right="20dp"
        android:bottom="10dp"
        android:top="10dp">

        <!-- Insert your shape here: -->
        <shape android:shape="rectangle"  >
            <solid android:color="#FE4C4C" />

            <!-- Padding for inner text-->
            <padding android:left="25dp" android:right="10dp" android:bottom="10dp" android:top="10dp" />
            <corners android:radius="5dp" />

        </shape>
    </item>
</layer-list>

然后从Activity中设置Drawable

MainActivity.java

Snackbar snack = Snackbar
                 .make(activity,"Hello World ",Snackbar.LENGTH_INDEFINITE);
        snack.getView()
        .setBackground(ContextCompat.getDrawable(getApplicationContext(),R.drawable.contianer_snackbar));
        snack.show();

结果


4

就我个人而言,没有提出的方法适用于(Android 9)
我是这样决定的。
我向布局中添加了一个不可见对象(anchor_view),并进行了如下设置:

snackbar.anchorView = anchor_view

3

试试这个:

Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "message", Snackbar.LENGTH_LONG);

View snackBarView = snackbar.getView();
            LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,      
LayoutParams.WRAP_CONTENT);

params.setMargins(left, top, right, bottom);

snackBarView.setLayoutParams(params);

snackbar.show();

3
控制Snackbar显示的关键是使用android.support.design.widget.CoordinatorLayout布局。如果没有它,您的Snackbar将始终显示在小设备底部填充,在大设备底部左侧填充。注意:您可以将CoordinatorLayout用作布局的根ViewGroup或布局树结构中的任何位置。
添加后,请确保将CoordinatorLayout(或子项)作为Snackbar.make()命令的第一个参数传递。
通过向CoordinatorLayout添加填充或边距,您可以控制位置并将Snackbar从屏幕底部移动。
材料设计指南规定Snackbar的最小和最大宽度。在小型设备上,您将看到它填充屏幕宽度,而在平板电脑上,您将看到Snackbar达到最大宽度而不填充屏幕宽度。

3

只需将其添加到您的主题中:

<item name="snackbarStyle">@style/SnackbarMessageStyle</item>

并添加样式:

<style name="SnackbarMessageStyle" parent="@style/Widget.MaterialComponents.Snackbar">
    <item name="android:layout_margin">@dimen/snackbarMessageMargin</item>
</style>

1
这个答案看起来更简洁,但是它并不起作用。你需要在 snackbar 中放置一些东西才能加载它吗? - Daniel Gomez Rico
它不起作用。在注意到这个答案之前,我已经尝试过了。 - Naimul Kabir

2

对于我来说,大多数编程方法都没有奏效,因为Snackbar.SnackbarLayout中的边距是由snackbar.show()在过程中应用的。所以这是我采取的方法,它起作用了:

    public void showNoInternet(){
    noInternetSnack = Snackbar.make(noInternetSnackParent, "No internet connection", Snackbar.LENGTH_INDEFINITE)
            .setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_SLIDE)
            .setBackgroundTint(PaletteUtils.getSolidColor(PaletteUtils.MATERIAL_RED));

    Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) noInternetSnack.getView();

    TextView snackText = snackbarLayout.findViewById(com.google.android.material.R.id.snackbar_text);
    snackText.setTextSize(getResources().getDimension(R.dimen.newsMoreTextSize)/3);
    snackText.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
    LinearLayout.LayoutParams llp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    llp.topMargin = -30;
    llp.bottomMargin = -30;
    snackText.setLayoutParams(llp);

    noInternetSnack.show();

    new Handler().postDelayed(() -> {
        ViewGroup.MarginLayoutParams llp2 = (ViewGroup.MarginLayoutParams) snackbarLayout.getLayoutParams();
        llp2.setMargins(0,8,0,0);
        snackbarLayout.setLayoutParams(llp2);
        }, 300);
}

然而,在活动主题中从 Theme.AppCompat 更改为 Theme.MaterialComponents.DayNight(还要检查是否在清单文件中的活动主题中使用了 Theme.AppCompat),对我来说起作用了,但默认情况下它适用于所有 snackbars。你可以像我使用这段代码一样添加边距来移除边距。 这里的主要问题是延迟 snackbarLayout.setLayoutParams(llp2); 以便应用更改到布局上。这主要用于特定用途的自定义 snackbar。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接