March 24, 2016

Android Material Design Bottom Sheets Tutorial

By admin

With the Arrival of the new version 23.2 of library support Android brings a new component that can enrich the user interface of some of our applications, calls Bottom Sheets. You can find a detailed description of this component in the guides design of Material design.

What is Bottom Sheets ?

A bottom sheet is a sheet of material that slides up from the bottom edge of the screen. Bottom sheets are displayed only as a result of a user-initiated action, and can be swiped up to reveal additional content. A bottom sheet can be a temporary modal surface or a persistent structural element of an app.

There are two major types of bottom sheets:

-> Persistent bottom sheet :- Normally used to display additional information to that shown in the main view. These panels have the same elevation as the main content and remain visible even when not being actively used.

-> Modal bottom sheet :- Commonly used as an alternative to simple menus or dialogs. They have a higher elevation than the main content, darken the display, and it is necessary to hide them continue to interact with the rest of the application.

Let’s Get it Working

In this tutorials we will learn how to use the bottom sheets. To really understand the usage of bottom sheets we will create an app. The App will show the usage of both the forms of this component.

Step 1 ) Update build.gradle file

Before you can use Bottom Sheet in your projects you need to add the following compile line to your Gradle dependencies block in your build.gradle file and rebuilt the project .

dependencies {
    ...
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.android.support:design:23.2.1'
}

Step 2) Update strings.xml .

Add the below string values to the string.xml located in res => values => strings.xml .

<resources>
    <string name="app_name">Bottom Sheets</string>
    <string name="text_welcome_message">Welcome to Android Tutorials Hub</string>
    <string name="text_dialog_bottom_sheet">Dialog Bottom Sheet</string>
    <string name="text_expand_me">Expand Me</string>
    <string name="text_collapse_me">Collapse Me</string>
    <string name="text_expand_bottom_sheet">Expand Bottom Sheet</string>
    <string name="text_collapse_bottom_sheet">Collapse Bottom Sheet</string>
    <string name="text_hide_bottom_sheet">Hide Bottom Sheet</string>
    <string name="text_show_bottom_sheet_dialog">Show Bottom Sheet Dialog</string>
</resources>

Step 3) Update dimens.xml .

Add the below dimensions to the dimens.xml located in res => values => dimens.xml .

<resources>
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>

Step 4) Update activity_main.xml .

Open the layout file for the MainActivity.java i.e activity_main.xml and add the below code in your layout file . The code will create four buttons and view for bottom sheet.

<?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"
    android:fitsSystemWindows="true"
    tools:context="com.androidtutorialshub.bottomsheets.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

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

    <!-- Main Content -->
    <include layout="@layout/content_main" />

    <!-- Bottom Sheet Content -->
    <include layout="@layout/content_bottom_sheet" />


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

content_main.xml .
Create a layout xml named content_main.xml and update the below code in that xml file. This code will create four buttons.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    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:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.androidtutorialshub.bottomsheets.MainActivity"
    tools:showIn="@layout/activity_main">

    <Button
        android:id="@+id/expand_bottom_sheet_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/text_expand_bottom_sheet" />
    <Button
        android:id="@+id/collapse_bottom_sheet_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/expand_bottom_sheet_button"
        android:text="@string/text_collapse_bottom_sheet" />
    <Button
        android:id="@+id/hide_bottom_sheet_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/collapse_bottom_sheet_button"
        android:text="@string/text_hide_bottom_sheet" />
    <Button
        android:id="@+id/show_bottom_sheet_dialog_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/hide_bottom_sheet_button"
        android:text="@string/text_show_bottom_sheet_dialog" />
</RelativeLayout>

content_bottom_sheet.xml .
Create a layout xml named content_bottom_sheet.xml and update the below code in that xml file. This code will create view for bottom sheet. Here you can see that in relative layout there are attributes declared app:layout_behavior=”@string/bottom_sheet_behavior to automatically respond to user gestures to expand or collapse the view.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottomSheetLayout"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:background="@android:color/holo_orange_light"
    android:padding="@dimen/activity_vertical_margin"
    app:behavior_hideable="true"
    app:behavior_peekHeight="60dp"
    app:layout_behavior="@string/bottom_sheet_behavior">

    <TextView
        android:id="@+id/bottomSheetHeading"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/text_expand_me"
        android:textAppearance="@android:style/TextAppearance.Large" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/bottomSheetHeading"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/activity_horizontal_margin"
        android:text="@string/text_welcome_message"
        android:textAppearance="@android:style/TextAppearance.Large" />
</RelativeLayout>

Step 5) Update MainActivity Class.

Now Open MainActivity.java and make some changes in code . Here we will see the how to handle bottom sheets and also see how it behaves in different states by checking the logcat.
Basically there are five states of Bottom sheet as follows :-
-> STATE_COLLAPSED: this collapsed state is the default and shows just a portion of the layout along the bottom. The height can be controlled with the app:behavior_peekHeight attribute (defaults to 0)
-> STATE_DRAGGING: the intermediate state while the user is directly dragging the bottom sheet up or down
-> STATE_SETTLING: that brief time between when the View is released and settling into its final position
-> STATE_EXPANDED: the fully expanded state of the bottom sheet, where either the whole bottom sheet is visible (if its height is less than the containing CoordinatorLayout) or the entire CoordinatorLayout is filled
-> STATE_HIDDEN: disabled by default (and enabled with the app:behavior_hideable attribute), enabling this allows users to swipe down on the bottom sheet to completely hide the bottom sheet

package com.androidtutorialshub.bottomsheets;

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // BottomSheetBehavior variable
    private BottomSheetBehavior bottomSheetBehavior;

    // TextView variable
    private TextView bottomSheetHeading;

    // Button variables
    private Button expandBottomSheetButton;
    private Button collapseBottomSheetButton;
    private Button hideBottomSheetButton;
    private Button showBottomSheetDialogButton;

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

        initViews();
        initListeners();


    }

    /**
     * method to initialize the views
     */
    private void initViews() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottomSheetLayout));
        bottomSheetHeading = (TextView) findViewById(R.id.bottomSheetHeading);
        expandBottomSheetButton = (Button) findViewById(R.id.expand_bottom_sheet_button);
        collapseBottomSheetButton = (Button) findViewById(R.id.collapse_bottom_sheet_button);
        hideBottomSheetButton = (Button) findViewById(R.id.hide_bottom_sheet_button);
        showBottomSheetDialogButton = (Button) findViewById(R.id.show_bottom_sheet_dialog_button);


    }


    /**
     * method to initialize the listeners
     */
    private void initListeners() {
        // register the listener for button click
        expandBottomSheetButton.setOnClickListener(this);
        collapseBottomSheetButton.setOnClickListener(this);
        hideBottomSheetButton.setOnClickListener(this);
        showBottomSheetDialogButton.setOnClickListener(this);

        // Capturing the callbacks for bottom sheet
        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(View bottomSheet, int newState) {

                if (newState == BottomSheetBehavior.STATE_EXPANDED) {
                    bottomSheetHeading.setText(getString(R.string.text_collapse_me));
                } else {
                    bottomSheetHeading.setText(getString(R.string.text_expand_me));
                }

                // Check Logs to see how bottom sheets behaves
                switch (newState) {
                    case BottomSheetBehavior.STATE_COLLAPSED:
                        Log.e("Bottom Sheet Behaviour", "STATE_COLLAPSED");
                        break;
                    case BottomSheetBehavior.STATE_DRAGGING:
                        Log.e("Bottom Sheet Behaviour", "STATE_DRAGGING");
                        break;
                    case BottomSheetBehavior.STATE_EXPANDED:
                        Log.e("Bottom Sheet Behaviour", "STATE_EXPANDED");
                        break;
                    case BottomSheetBehavior.STATE_HIDDEN:
                        Log.e("Bottom Sheet Behaviour", "STATE_HIDDEN");
                        break;
                    case BottomSheetBehavior.STATE_SETTLING:
                        Log.e("Bottom Sheet Behaviour", "STATE_SETTLING");
                        break;
                }
            }


            @Override
            public void onSlide(View bottomSheet, float slideOffset) {

            }
        });


    }

    /**
     * onClick Listener to capture button click
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.collapse_bottom_sheet_button:
                // Collapsing the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                break;
            case R.id.expand_bottom_sheet_button:
                // Expanding the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                break;
            case R.id.hide_bottom_sheet_button:
                // Hiding the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                break;
            case R.id.show_bottom_sheet_dialog_button:
                
                break;

        }
    }
}

The above code would result a screen like this:

Collapse Bottom Sheet

Collapse Bottom Sheet


Expanded Bottom Sheet

Expanded Bottom Sheet

Step 6 ) Create content_dialog_bottom_sheet.xml .

Create a layout xml named content_dialog_bottom_sheet.xml and update the below code in that xml file. This code will create view for bottom sheet dialog.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottomSheetLayout"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:background="@android:color/holo_red_light"
    android:padding="@dimen/activity_vertical_margin"
    app:behavior_hideable="true"
    app:behavior_peekHeight="60dp"
    app:layout_behavior="@string/bottom_sheet_behavior">

    <TextView
        android:id="@+id/bottomSheetHeading"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/text_dialog_bottom_sheet"
        android:textAppearance="@android:style/TextAppearance.Large" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/bottomSheetHeading"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/activity_horizontal_margin"
        android:text="@string/text_welcome_message"
        android:textAppearance="@android:style/TextAppearance.Large" />
</RelativeLayout>

Step 7) Create CustomBottomSheetDialogFragment Class.

Create a class named CustomBottomSheetDialogFragment and extend it by BottomSheetDialogFragment .

package com.androidtutorialshub.bottomsheets;

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

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.content_dialog_bottom_sheet, container, false);
        return v;
    }


}

Step 8) Update onClick() Listener.

Now update the onClick() Listener with the below code . Here in case R.id.show_bottom_sheet_dialog_button: i created the object of CustomBottomSheetDialogFragment and called the funtion show . It will show the Bottom Sheet Dialog on the screen .

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.collapse_bottom_sheet_button:
                // Collapsing the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                break;
            case R.id.expand_bottom_sheet_button:
                // Expanding the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                break;
            case R.id.hide_bottom_sheet_button:
                // Hiding the bottom sheet
                bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
                break;
            case R.id.show_bottom_sheet_dialog_button:
                // Opening the Dialog Bottom Sheet
                new CustomBottomSheetDialogFragment().show(getSupportFragmentManager(), "Dialog");
                break;

        }
    }

The above code would result a screen like this:

Bottom Sheet Dialog

Bottom Sheet Dialog

DownloadCode
github

Enjoy Coding and Share Knowledge