Android Bottom Sheet Example - Truiton
Skip to content

Android Bottom Sheet Example

Android Bottom Sheet - Featured

When in 2014, Google introduced Material Design, they introduced many new design components, like Floating Action button, Tabs, Cards, and Bottom Sheets for Android. Although most of the new components were not available for Android at that moment. But over time they released a support library by the name of Design Support Library. Which thankfully helped the developers to utilize the power of material design on Android. Recently a new design component was introduced in this support library called the Bottom Sheet. Here in this Android Bottom Sheet example, we would make a short example using the new component to understand its working. But first lets understand what is an Android Bottom Sheet.

According to material design, Bottom Sheets can be of two types: Persistent and Modal. Here in this example we would make samples for both types of Android Bottom sheets. As per documentation persistent bottom sheets are supposed to be in-app content. Hence they are included right inside the main layout. In a way they are supposed to be integrated with the app or screen. On the other hand Modal Bottom sheets are a little different; they are supposed to be used as the layer on top of your app. Mostly they are inferred as an external entity, like a menu. Also since they are like menus, therefore if they are visible to the user, they do not allow the user to interact with main screen in background. First they need to dismiss the Android Bottom Sheet, only then the user would be allowed to interact with main activity. Lets learn more about them in the next sections, also full source code is available for this example at the bottom of this write-up. But first, lets please include these dependencies in our build.gradle file:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile 'com.android.support:design:24.0.0'
}

Android Bottom Sheet : Persistent

To make some content beautifully slide in and out of a screen, we can use the persistent Bottom Sheets on Android. To make a view as persistent Bottom Sheet in your screen all you need to do is have CoordinatorLayout at the top level of your layout. Next a behavior should be specified in the layout you need to make a Bottom Sheet. To understand better lets define the layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.truiton.bottomsheet_persistent.MainActivity">

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin">

            <ImageView
                android:id="@+id/image"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:src="@mipmap/truiton"/>

            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/image"
                android:layout_centerHorizontal="true"
                android:text="Show Bottom Sheet"/>
        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>

    <RelativeLayout
        android:id="@+id/design_bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:behavior_hideable="true"
        app:behavior_peekHeight="50dp"
        app:elevation="4dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            android:id="@+id/bottomsheet_text"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="Introducing Bottom Sheets"
            android:textColor="#FFFFFF"/>

    </RelativeLayout>


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

This would result in a screen with Android Bottom sheet like this:

One of the great parts about persistent Bottom Sheets is that, they can be dragged to go full screen, even if they don’t have the content for a full page. On the other hand Modal Bottom Sheets does not allow this.

Also if you closely observe the Android bottom sheet shown above, you may see that it stays below the Action bar. If you wish to make it go over the action bar. Please change the activity theme to Theme.AppCompat.Light.NoActionBar and add the elevation of 4dp in Bottom Sheet. It would start sliding right over the Toolbar (if added). Next lets have a look at the java file for this screen.

package com.truiton.bottomsheet_persistent;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View bottomSheet = findViewById(R.id.design_bottom_sheet);
        final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
        behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                switch (newState) {
                    case BottomSheetBehavior.STATE_DRAGGING:
                        Log.i("BottomSheetCallback", "BottomSheetBehavior.STATE_DRAGGING");
                        break;
                    case BottomSheetBehavior.STATE_SETTLING:
                        Log.i("BottomSheetCallback", "BottomSheetBehavior.STATE_SETTLING");
                        break;
                    case BottomSheetBehavior.STATE_EXPANDED:
                        Log.i("BottomSheetCallback", "BottomSheetBehavior.STATE_EXPANDED");
                        break;
                    case BottomSheetBehavior.STATE_COLLAPSED:
                        Log.i("BottomSheetCallback", "BottomSheetBehavior.STATE_COLLAPSED");
                        break;
                    case BottomSheetBehavior.STATE_HIDDEN:
                        Log.i("BottomSheetCallback", "BottomSheetBehavior.STATE_HIDDEN");
                        break;
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                Log.i("BottomSheetCallback", "slideOffset: " + slideOffset);
            }
        });

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (behavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                } else {
                    behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                }
            }
        });
    }
}

In the above piece of code, you may see that I have added a BottomSheetBehavior callback interface, to listen to the changes in Bottom Sheet states. Although in the above code its not serving any purpose, but its added for reference. Full source code is available here:

Source Code

Android Bottom Sheet : Modal

Second type of Bottom Sheet is the modal sheet. According to the documentation this component should act as a menu or a sheet which does not allow the users to interact with main screen until it is dismissed. Surprisingly when speaking of Android, this design pattern is similar to a dialog box. Hence a new class BottomSheetDialogFragment was introduced; extending the AppCompatDialogFragment. Which resulted in a perfect modal type Android Bottom Sheet.

Now technically speaking; when we talk of modal type Android bottom sheets, we have to create an XML outside of the activity separately to inflate in the BottomSheetDialogFragment. To start off lets have a look at the XMLs first:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/colorAccent"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Introducing Modal Bottom Sheet"
        android:textColor="#FFFFFF"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
        android:textColor="#FFFFFF"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
        android:textColor="#FFFFFF"/>

</LinearLayout>

Also have a look at the XML for MainActivity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.truiton.bottomsheet_modal.MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:src="@mipmap/truiton"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image"
        android:layout_centerHorizontal="true"
        android:text="Show Modal Bottom Sheet"/>
</RelativeLayout>

Now that we have XMLs in place. Lets have a look at some code for the MainActivity:

package com.truiton.bottomsheet_modal;

import android.os.Bundle;
import android.support.design.widget.BottomSheetDialogFragment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final BottomSheetDialogFragment myBottomSheet = MyBottomSheetDialogFragment.newInstance("Modal Bottom Sheet");

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                myBottomSheet.show(getSupportFragmentManager(), myBottomSheet.getTag());
            }
        });
    }
}

Over here you may see that, to actually show a Bottom Sheet we are using an instance of the BottomSheetDialogFragment. Therefore lets have a look at the class for bottom sheet.

package com.truiton.bottomsheet_modal;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * Created by MG on 17-07-2016.
 */
public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {

    String mString;

    static MyBottomSheetDialogFragment newInstance(String string) {
        MyBottomSheetDialogFragment f = new MyBottomSheetDialogFragment();
        Bundle args = new Bundle();
        args.putString("string", string);
        f.setArguments(args);
        return f;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mString = getArguments().getString("string");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.bottom_sheet_modal, container, false);
        TextView tv = (TextView) v.findViewById(R.id.text);
        return v;
    }
}

As you can see, the working of above class is just like any DialogFragment in Android. Hence we inflated the layout in onCreateView() method, which made the Bottom Sheet to look like:

Another interesting thing about the modal type android bottom sheets is that, they render themselves on top of the view hierarchy making the background a little dull. Also this type of Bottom sheet automatically covers the action bar or toolbar, as its on top of the view hierarchy. Another thing that distinguishes between the modal and persistent Bottom sheets is that; modal sheets expand until the content is visible, once whole content is visible they don’t expand any further. Unlike the persistent type Android bottom sheet which cover the screen regardless of content. To view the full source code, please refer to the link below:

Source Code

Many apps are starting to use this component; as it has the inbuilt sliding feature, which adds on to a good user experience. In a way the new bottom sheet design component could turn out to be very useful in an Android app. As it gives a new hidden space within the screen, which the user can relate to and slide out at any time. Also since now it has been fully integrated in to the Android platform, I recommend all of the apps should use this component to make apps more interactive and more connected to the user. Hope this helps, connect with us on Twitter, Facebook and Google+ for more updates.

2 thoughts on “Android Bottom Sheet Example”

Leave a Reply

Your email address will not be published. Required fields are marked *