How to show Snackbar at top of the screen

93,060

Solution 1

It is possible to make the snackbar appear on top of the screen using this:

Snackbar snack = Snackbar.make(parentLayout, str, Snackbar.LENGTH_LONG);
View view = snack.getView();
FrameLayout.LayoutParams params =(FrameLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snack.show();

From the OP:

I had to change the first line:

Snackbar snack = Snackbar.make(findViewById(android.R.id.content), "Had a snack at Snackbar", Snackbar.LENGTH_LONG);

Solution 2

CoordinatorLayout coordinatorLayout=(CoordinatorLayout)findViewById(R.id.coordinatorLayout);
Snackbar snackbar = Snackbar.make(coordinatorLayout, "Text", Snackbar.LENGTH_LONG);
View view = snackbar.getView();
CoordinatorLayout.LayoutParams params=(CoordinatorLayout.LayoutParams)view.getLayoutParams();
params.gravity = Gravity.TOP;
view.setLayoutParams(params);
snackbar.show();

Solution 3

Kotlin-

    val snackBarView = Snackbar.make(view, "SnackBar Message" , Snackbar.LENGTH_LONG)
    val view = snackBarView.view
    val params = view.layoutParams as FrameLayout.LayoutParams
    params.gravity = Gravity.TOP
    view.layoutParams = params
    view.background = ContextCompat.getDrawable(context,R.drawable.custom_drawable) // for custom background
    snackBarView.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE
    snackBarView.show()

below line will resolve the animation issue.

snackBarView.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE

Alternate solution- snackBarView.anchorView = mention viewId above whom you want to show SnackBar

Solution 4

You can do the following to position a SnackBar anywhere inside a layout (This method has No Animation Issues)

1) According to:

https://developer.android.com/reference/android/support/design/widget/Snackbar.html#make(android.view.View, java.lang.CharSequence, int)

Snackbar make (View view, CharSequence text, int duration)

Make a Snackbar to display a message Snackbar will try and find a parent view to hold Snackbar's view from the value given to view. Snackbar will walk up the view tree trying to find a suitable parent, which is defined as a CoordinatorLayout or the window decor's content view, whichever comes first.

So, one can position a snackBar anywhere inside a layout simply by adding a Coordinator Layout in the desired location and using that Coordinator Layout as the view argument inside Snackbar.make method above.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity"
android:orientation="vertical"
android:id="@+id/rl"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Coordinator Layout used to position the SnackBar -->

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/cl"
    android:layout_alignParentTop="true"
    android:background="@android:color/transparent">
</android.support.design.widget.CoordinatorLayout>

<!-- add your layout here -->

</RelativeLayout>

2) The Coordinator Layout used to display the SnackBar should be on top of all other views (highest elevation). In order to do that, one might either call bringToFront() on the coordinator layout or elevate the coordinator layout (add android:elevation="10dp" for example)

3) At this point the snackBar will show up in the desired location, but the snackBar is displayed with a bottom to top animation (default behavior). In order to achieve a top to bottom animation, you can do the following:

  • Rotate Coordinator layout used inside Snackbar.make method by 180 degrees

4) After step 3, the snackBar will be displayed with a top to bottom animation, but the message and action text are rotated and the gravity is reversed, so as a final step, I did the following:

  • Got SnackBar View, found the LinearLayout holding the TextView responsible about displaying the message and the TextView responsible about the action, and rotated the parent LinearLayout by 180 degress

5) Example:

public class MainActivity extends AppCompatActivity {

private final String TAG = MainActivity.class.getSimpleName();
private RelativeLayout rl;
private CoordinatorLayout cl;
private CoordinatorLayout cl1;
private CoordinatorLayout cl2;
private CoordinatorLayout cl3;
private CoordinatorLayout cl4;
private Snackbar snackbar_updated;
private Snackbar snackbar_updated1;
private Snackbar snackbar_updated2;
private Snackbar snackbar_updated3;
private Snackbar snackbar_updated4;
private Snackbar snackbar_ordinary;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rl = (RelativeLayout) findViewById(R.id.rl);
    cl = (CoordinatorLayout) findViewById(R.id.cl);
    cl1 = (CoordinatorLayout) findViewById(R.id.cl1);
    cl2 = (CoordinatorLayout) findViewById(R.id.cl2);
    cl3 = (CoordinatorLayout) findViewById(R.id.cl3);
    cl4 = (CoordinatorLayout) findViewById(R.id.cl4);
    cl.bringToFront();
    cl1.bringToFront();
    cl2.bringToFront();
    cl3.bringToFront();
    cl4.bringToFront();

    snackbar_updated = Snackbar.make(cl, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    final Snackbar.SnackbarLayout snackBarLayout = (Snackbar.SnackbarLayout) snackbar_updated.getView();
    for (int i = 0; i < snackBarLayout.getChildCount(); i++) {
        View parent = snackBarLayout.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated1 = Snackbar.make(cl1, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated1.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    final Snackbar.SnackbarLayout snackBarLayout1 = (Snackbar.SnackbarLayout) snackbar_updated1.getView();
    for (int i = 0; i < snackBarLayout1.getChildCount(); i++) {
        View parent = snackBarLayout1.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated2 = Snackbar.make(cl2, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated2.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    snackbar_updated3 = Snackbar.make(cl3, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated3.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    /** Snackbar message and action TextViews are placed inside a LinearLayout
     */
    Snackbar.SnackbarLayout snackBarLayout3 = (Snackbar.SnackbarLayout) snackbar_updated3.getView();
    for (int i = 0; i < snackBarLayout3.getChildCount(); i++) {
        View parent = snackBarLayout3.getChildAt(i);
        if (parent instanceof LinearLayout) {
            ((LinearLayout) parent).setRotation(180);
            break;
        }
    }

    snackbar_updated4 = Snackbar.make(cl4, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_updated4.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    snackbar_ordinary = Snackbar.make(rl, "Message", Snackbar.LENGTH_INDEFINITE);
    snackbar_ordinary.setAction("Ok", new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });

    rl.post(new Runnable() {
        @Override
        public void run() {
            snackbar_updated.show();
            rl.postDelayed(new Runnable() {
                @Override
                public void run() {
                    snackbar_updated1.show();
                    rl.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            snackbar_updated2.show();
                            rl.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    snackbar_updated3.show();
                                    rl.postDelayed(new Runnable() {
                                        @Override
                                        public void run() {
                                            snackbar_updated4.show();
                                            rl.postDelayed(new Runnable() {
                                                @Override
                                                public void run() {
                                                    snackbar_ordinary.show();
                                                }
                                            }, 2000);
                                        }
                                    }, 2000);
                                }
                            }, 2000);
                        }
                    }, 2000);
                }
            }, 2000);
        }
    });

}

}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity"
android:orientation="vertical"
android:id="@+id/rl"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Coordinator Layout used to position the SnackBar -->

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/cl"
    android:rotation="180"
    android:layout_alignParentTop="true"
    android:background="@android:color/transparent">
</android.support.design.widget.CoordinatorLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignParentTop="true"
    android:orientation="vertical">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:itemIconTint="#333"
        app:itemTextColor="#333"
        app:layout_collapseMode="pin"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

</android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@id/appbar"
        android:layout_gravity="bottom">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_top"
            android:text="Layout Top"
            android:gravity="center"
            android:textSize="15sp"
            android:textColor="@android:color/white"
            android:layout_alignParentTop="true"
            android:background="@color/colorAccent">
        </TextView>

        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl1"
            android:rotation="180"
            android:layout_below="@id/tv_top"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>


        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl2"
            android:paddingBottom="75dp"
            android:layout_centerInParent="true"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>

        <!-- Coordinator Layout used to position the SnackBar -->

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_center"
            android:text="Center"
            android:gravity="center"
            android:textSize="15sp"
            android:layout_centerInParent="true"
            android:textColor="@android:color/white"
            android:background="@color/colorAccent">
        </TextView>

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl3"
            android:rotation="180"
            android:paddingBottom="75dp"
            android:layout_centerInParent="true"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:id="@+id/tv_bottom"
            android:text="Layout Bottom"
            android:gravity="center"
            android:textSize="15sp"
            android:textColor="@android:color/white"
            android:layout_alignParentBottom="true"
            android:background="@color/colorAccent">
        </TextView>

        <!-- Coordinator Layout used to position the SnackBar -->

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cl4"
            android:layout_above="@id/tv_bottom"
            android:background="@android:color/transparent">
        </android.support.design.widget.CoordinatorLayout>


    </RelativeLayout>

</RelativeLayout>

</RelativeLayout>

6) Result:

result

Solution 5

Combined solution from the above ones:

final ViewGroup.LayoutParams params = snackbar.getView().getLayoutParams();
if (params instanceof CoordinatorLayout.LayoutParams) {
    ((CoordinatorLayout.LayoutParams) params).gravity = Gravity.TOP;
} else {
    ((FrameLayout.LayoutParams) params).gravity = Gravity.TOP;
}
snackbar.getView().setLayoutParams(params);

Still suffers from the improper animation.

Share:
93,060
Pankaj
Author by

Pankaj

I like to code each n every day and develop some good mobile app.

Updated on July 09, 2022

Comments

  • Pankaj
    Pankaj almost 2 years

    As the Android documentation says

    Snackbars provide lightweight feedback about an operation. They show a brief message at the bottom of the screen on mobile and lower left on larger devices.

    Is there any alternative by which we can show snackbars at top of the screen instead of the bottom?

    Right now I am doing something like this which shows a snackbar at the bottom of the screen.

    Snackbar.make(findViewById(android.R.id.content), "Hello this is a snackbar!!!", 
    Snackbar.LENGTH_LONG).setAction("Undo", mOnClickListener)
    .setActionTextColor(Color.RED)
    .show();
    
  • Jared Rummler
    Jared Rummler about 8 years
    The animation on the SnackBar slides up which makes this look horrible. I haven't tried it yet, but here is a library project that shows a SnackBar with the correct animations: github.com/AndreiD/TSnackBar I feel like I'm in ##java on IRC.
  • Devidas M Das
    Devidas M Das almost 8 years
    This one is working . Adarsh Yadav's solution is down casting CoordinatorLayout to FrameLayout there may be chance to crash the app
  • Maragues
    Maragues almost 8 years
    If you are using a Coordinator layout somewhere above in the hierarchy, this code crashes with a ClassCastException, CoordinatorLayout$LayoutParams cannot be cast to FrameLayout$LayoutParams. Support v24 only uses a FrameLayout as snackbar container if it doesn't find a CoordinatorLayout ancestor or if its id is android.R.id.content. See SnackBar.findSuitableParent for implementation details. You can hack the system by setting your FrameLayout's id to android.R.id.content, but that may stop working in the future.
  • hornet2319
    hornet2319 almost 8 years
    It's quite ugly solution. If you are using any layout (except FrameLayout) it will crash.
  • Abhijit
    Abhijit over 7 years
    I am using Relative Layout and it is working, but animation is bad
  • Paresh P.
    Paresh P. over 7 years
    Be safe, Using FrameLayout.LayoutParams may result in crash. CoordinatorLayout.LayoutParams works fine.
  • omikes
    omikes about 6 years
    And they scored a very rare badge for this answer! One of three answers total. Come back Vijayan, we miss you.
  • lionscribe
    lionscribe over 5 years
    Pretty silly. Just use `ViewGroup.MarginLayoutParams params =(ViewGroup.MarginLayoutParams)view.getLayoutParams();' which is the parent for most layouts.
  • filthy_wizard
    filthy_wizard about 5 years
    yup. toast now just fills screen. still appears bottom up. not top down
  • Monica Aspiras Labbao
    Monica Aspiras Labbao about 5 years
    This works regardless of the parent layout whether it's a FrameLayout, LinearLayout, ConstraintLayout, etc.
  • Ssubrat Rrudra
    Ssubrat Rrudra over 4 years
    How to do this with ConstraintLayout?
  • Rob Lyndon
    Rob Lyndon over 4 years
    Very sneaky. Works perfectly.
  • enyciaa
    enyciaa over 4 years
    Love it, combined with @Deepak's answer you can avoid the rotation part of this answer by simply using a fade animation on the snackbar (instead of slide)
  • Cfun
    Cfun over 3 years
    I believe this answer is not valid anymore target android 9.0: View view = snack.getView(); should be replaced by View view = snack.View; I don't know about the rest. Any chance you revive your answer for 2020?
  • AndreasReiff
    AndreasReiff over 3 years
    Works! Easy solution.
  • AndreasReiff
    AndreasReiff over 3 years
    Does only work with Snackbar.LENGTH_INDEFINITE though
  • Nelson Ramirez
    Nelson Ramirez almost 3 years
    It's worth noting that snackBarView.animationMode = BaseTransientBottomBar.ANIMATION_MODE_FADE is not available in older versions of the material library. Not sure which version this animation mode first appears in, but it's definitely in material:1.4.0
  • user3088071
    user3088071 over 2 years
    try snackbarView.setRotation(180);
  • jhfdr3s
    jhfdr3s over 2 years
    Unfortunately material:1.0.0 does not have that property