Reputation: 6657
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:
Example B:
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
Reputation: 4823
Updating dependency might work.
https://github.com/material-components/material-components-android/releases/tag/1.6.0
Fixed the issue that setting margins programmatically does not work (d5856fd)
Upvotes: 0
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
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
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
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
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();
Upvotes: 8
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>
Upvotes: 16
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:
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>
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()
}
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
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
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
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
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
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
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
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
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
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
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
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
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