AndroidEnthusiast
AndroidEnthusiast

Reputation: 6657

Add margins to Snackbar view

I'm updating my current app to use snackbars, in the Google spec they show various ways of using them http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs

Example A:

Snackbar with margin

Example B:

Snackbar pinned to layout

Here's my code atm:

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

I get the result in Example B,

How can i add margins?

Upvotes: 28

Views: 32284

Answers (20)

Igor Maximo
Igor Maximo

Reputation: 1

Just add this code/call this function after snack.show()

...

snack.show()
snack.setAnimToUnblockBottomNavBar()



... 

private fun Snackbar.setAnimToUnblockBottomNavBar() {
        val animator = ValueAnimator.ofInt(0, 150)
        animator.addUpdateListener { valueAnimator ->
            val valueAnim = valueAnimator.animatedValue
            if (valueAnim is Int) {
                try {
                    val snackBarView: View = this.view
                    val params = snackBarView.layoutParams as FrameLayout.LayoutParams
                    params.setMargins(0, 0, 0, valueAnim)
                    snackBarView.layoutParams = params
                } catch (_: Exception) { /* do nothing */ }
            }
        }
        animator.start()
    }

Upvotes: 0

Dh. Yaduvanshi
Dh. Yaduvanshi

Reputation: 31

Most of the programmatically applied methods didn't work out for me because the margins in Snackbar.SnackbarLayout are somehow applied by snackbar.show() in the process. So this is how I approached it and it worked:

    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);
}

However, changing from Theme.AppCompat to Theme.MaterialComponents.DayNight in activity's theme along with app theme (double check if you are using Theme.AppCompat in activities theme in manifest) worked out for me but it applied to all snackbars by default. You can add margins just like I used this code to remove margins. the main thing here is to delay snackbarLayout.setLayoutParams(llp2); so that the changes are applied to the layout. This is mainly for the use when you make a custom snackbar for specific use.

Upvotes: 2

Mrunal Mahakala
Mrunal Mahakala

Reputation: 1

The other answers did not work for me. I have implemented this instead:

SnackBar.class

public  class SnackBar{  
Context context;
Snackbar getSnackbar(View v, String s, View.OnClickListener listener, String action){
    Snackbar sn = Snackbar.make(v, "" + s, Snackbar.LENGTH_LONG);
    sn.setAction("" + action, listener);
    sn.setActionTextColor(Color.CYAN);
    sn.show();
 sn.getView().setBackground(ContextCompat.getDrawable(context,R.drawable.snackbar_shape));
    return sn;
}

in MainActivity.class include

MainActivity.class:

  // Snackbar.make(v,"Notification for pressing button",Snackbar.LENGTH_LONG).show();
            final SnackBar snackBar=new SnackBar();
           snackBar.context=MainActivity.this;
           snackBar.getSnackbar(v, "Notification for pressing ", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e(TAG,"cancelled");
                    snackBar.onClick=true;
                    
                }
            }, "cancel");

in drawable directory

snackbar_shape.xml

<item
    android:left="20dp"
    android:right="20dp"
    android:bottom="10dp"
    android:top="10dp">     
    <shape android:shape="rectangle"  >
        <solid android:color="#F31E1E1E" />    
        <padding android:left="25dp"android:right="25dp" android:bottom="10dp"android:top="10dp" />
        <corners android:radius="7dp" />

    </shape>
</item>

Upvotes: 0

Gilad Raz
Gilad Raz

Reputation: 155

It wasn't working for me programitly, so I did it from the styles.xml

Create this style

 <style name="hpr_snackbar_message_style" parent="@style/Widget.MaterialComponents.Snackbar">
        <item name="android:layout_margin">@null</item>
        <!-- Use default Snackbar margins for top/left/right -->
        <item name="android:layout_marginTop">@dimen/mtrl_snackbar_margin</item>
        <item name="android:layout_marginLeft">@dimen/snackbar_margin</item>
        <item name="android:layout_marginRight">@dimen/snackbar_margin</item>
        <!-- Custom bottom margin, this could work for top/left/right too -->
        <item name="android:layout_marginBottom">@dimen/snackbar_margin</item>
    </style>

Add it to your parent theme

 <style name="parent_theme" parent="Theme.AppCompat.Light">
        <item name="snackbarStyle">@style/hpr_snackbar_message_style</item>

Upvotes: 1

Bhavin Dhodia
Bhavin Dhodia

Reputation: 159

Adding CoordinatorLayout or Frame Layout and then setting margin didn't work for me

To tackle this problem use Drawable Background where use item to set Margin and shape to set desired Padding

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>

And then from Activity set that 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();

Result

Upvotes: 8

Gabriele Mariotti
Gabriele Mariotti

Reputation: 364858

With the Material Components library you can use the snackbarStyle attribute in your app theme:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
    <item name="snackbarStyle">@style/MySnackbar</item>
</style>

with:

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

enter image description here

Upvotes: 16

Zidd
Zidd

Reputation: 41

None of the above solutions worked for me. This is my solution, my idea is create the background with transparent side, so looks like a margin. Try this works for me:

  1. Create drawable for background

     <?xml version="1.0" encoding="utf-8"?>
     <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
         <item>
             <shape android:shape="rectangle">
                 <solid android:color="@color/transparent" />
             </shape>
         </item>
         <item android:top="16dp" android:bottom="16dp" android:left="16dp" android:right="16dp">
             <shape android:shape="rectangle">
                 <solid android:color="#323232" />
                 <corners android:radius="4dp" />
             </shape>
         </item>
     </layer-list>
    
  2. Using kotlin extension to show Snackbar and add the padding

     private fun Snackbar.show(context: Context) {
         this.view.setPadding(Dpx.dpToPx(16), Dpx.dpToPx(16), Dpx.dpToPx(16), Dpx.dpToPx(16))
         this.view.background = context.getDrawable(R.drawable.bg_snackbar)
         show()
     }
    
  3. Call Snackbar make

     Snackbar.make(view, R.string.my_message, Snackbar.LENGTH_SHORT).show(this)
    

Thats all. Tell me if that works, thanks...

Upvotes: 0

tosh17
tosh17

Reputation: 192

Personally, none of the proposed methods has come up (Android 9)
I decided in the following way.
I added an invisible object (anchor_view) to the layout and made:

snackbar.anchorView = anchor_view

Upvotes: 4

M.Namjo
M.Namjo

Reputation: 522

To set margin:

View viewInSnk = snkbr.getView();
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) snkbr.getView().getLayoutParams();
params.setMargins(5, 5, 5, 5);
snkbr.getView().setLayoutParams(params);

and to set round corner:

viewInSnk.setBackgroundDrawable(getResources().getDrawable(R.drawable.snackbar_shape));

and for shape :

<shape android:shape="rectangle"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#313131"/>
    <corners android:radius="4dp"/>
</shape>

Upvotes: 0

Frank
Frank

Reputation: 12308

Just add it in your theme:

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

And add the style:

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

Upvotes: 3

M.Usman
M.Usman

Reputation: 2119

None of the above solutions worked for me.

But, I got one trick that we can use with the help of translation.

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

you can find convertDpToPixel method here

Upvotes: 25

Shivanand Darur
Shivanand Darur

Reputation: 3224

If you want to apply margin to only specific side(s), you shall also achieve it as below. For example to apply only bottom margin,

 Snackbar.make(yourContainerView, getString(R.string.your_snackbar_message), Snackbar.LENGTH_LONG_orWhateverYouWant).apply {
    val params = view.layoutParams as CoordinatorLayout.LayoutParams
    params.anchorId = R.id.your_anchor_id
    params.anchorGravity = Gravity.TOP_orWhateverYouWant
    params.gravity = Gravity.TOP_orWhateverYouWant
    params.bottomMargin = 20 // in pixels
    view.layoutParams = params
    show()
}

Upvotes: 1

Dima DEF
Dima DEF

Reputation: 1

My solution in Kotlin extension:

    fun showSnackBarWithConfirmation(text: String, view: View, action: () -> Unit)  =
        Snackbar.make(view, text, Snackbar.LENGTH_LONG).apply {
            this.view.findViewById(R.id.snackbar_text)
                .setTextColor(view.context.color(R.color.colorBackgroundLight))
            this.view.setBackgroundResource(view.context.color(R.color.colorBackgroundLight))

setAction(view.context.getString(R.string.common_ok)) { action.invoke() } (this.view.layoutParams as ViewGroup.MarginLayoutParams) .apply { setMargins(56,0,56,300) } show() }

Upvotes: 0

Azizur Rehman
Azizur Rehman

Reputation: 2133

For kotlin developers, just some handy extension that I use,

inline fun View.snack(message:String, left:Int = 10, top:Int = 10, right:Int = 10, bottom:Int = 10, duration:Int = Snackbar.LENGTH_SHORT){
 Snackbar.make(this, message, duration).apply {

     val params = CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT )
     params.setMargins(left, top, right, bottom)
     params.gravity = Gravity.BOTTOM
     params.anchorGravity = Gravity.BOTTOM

     view.layoutParams = params
     show()
 }
}


inline fun View.longSnack(message:String){
   snack(message, duration = Snackbar.LENGTH_LONG)
}

Upvotes: 1

Vodet
Vodet

Reputation: 1519

I just add my solution because the @BamsMamx solution's didn't work I need to add 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();
}

Upvotes: 9

BamsBamx
BamsBamx

Reputation: 4256

In addition to Saeid's answer, you can get the default SnackBar layout params and modify them as you want:

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();
}

Upvotes: 29

Vlad
Vlad

Reputation: 8572

This works for me
container is parent tag which is CoordinatorLayout
R.id.bottom_bar is a view on which above snackbar should be shown

    Snackbar.make(container, getString(R.string.copied), Snackbar.LENGTH_LONG).apply {
        val params = view.layoutParams as CoordinatorLayout.LayoutParams
        params.anchorId = R.id.bottom_bar
        params.anchorGravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
        params.gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
        view.layoutParams = params
        show()
    }

if yout want additional margin then simply add padding to R.id.bottom_bar. This only works

Upvotes: 0

Saeid
Saeid

Reputation: 2321

Try this:

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();

Upvotes: 3

BrentM
BrentM

Reputation: 5757

The key to controlling the Snackbar display is using a android.support.design.widget.CoordinatorLayout Layout. Without it your Snackbar will always be displayed filled at the bottom on small devices and at the bottom left of large devices. Note: You may use the CoordinatorLayout as the root ViewGroup of your layout or anywhere in your layout tree structure.

After adding it, ensure you are passing the CoordinatorLayout (or child) as the first argument of the Snackbar.make() command.

By adding padding or margins to your CoordinatorLayout you can control the position and move the Snackbar from the bottom of the screen.

The material design guidelines specify a minimum and maximum width of the Snackbar. On small devices you will see it fill the width of the screen, while on tablets you will see the Snackbar hit the maximum width and not fill the width of the screen.

Upvotes: 3

Related Questions