Persistent Bottom Sheet in Android

Full project with source code to create a persistent bottom sheet, which we can drag up and down to show and hide its content. For the sheet we will use a NestedScrollView and set it’s layout_behavior to “BottomSheetBehavior” to tell the system that we want to use this NestedScrollView as our bottom sheet. We will also define a peekHeight and set hideable to true, so we can completely swipe it off the screen. In Java code we will then also collapse and expand it programmatically (on button click) by calling setState on our BottomSheetBehavior and passing a state constant to it. Also we will listen for state changes on our bottom sheet by setting a BottomSheetCallback to it and react to STATE_COLLAPSED, STATE_DRAGGING, STATE_EXPANDED, STATE_HIDDEN, STATE_SETTLING and onSlide

activity_main.xml

<?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="tech.codingpoint.persistentbottomsheetexample.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <Button
            android:id="@+id/button_expand"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="expand" />

        <Button
            android:id="@+id/button_collapse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="collapse" />

        <TextView
            android:id="@+id/text_view_state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="State"
            android:textColor="@android:color/black"
            android:textSize="30sp" />

    </LinearLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="350dp"
        android:background="@android:color/holo_blue_light"
        app:behavior_hideable="true"
        app:behavior_peekHeight="55dp"
        app:layout_behavior="@string/bottom_sheet_behavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="16dp"
            android:text="codingpoint"
            android:textSize="16sp" />

    </android.support.v4.widget.NestedScrollView>

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

MainActivity.java

package tech.codingpoint.persistentbottomsheetexample;

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

public class MainActivity extends AppCompatActivity {
    private BottomSheetBehavior mBottomSheetBehavior;
    private TextView mTextViewState;

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

        View bottomSheet = findViewById(R.id.bottom_sheet);

        mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

        mTextViewState = findViewById(R.id.text_view_state);

        Button buttonExpand = findViewById(R.id.button_expand);
        Button buttonCollapse = findViewById(R.id.button_collapse);

        buttonExpand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        buttonCollapse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            }
        });

        mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                switch (newState) {
                    case BottomSheetBehavior.STATE_COLLAPSED:
                        mTextViewState.setText("Collapsed");
                        break;
                    case BottomSheetBehavior.STATE_DRAGGING:
                        mTextViewState.setText("Dragging...");
                        break;
                    case BottomSheetBehavior.STATE_EXPANDED:
                        mTextViewState.setText("Expanded");
                        break;
                    case BottomSheetBehavior.STATE_HIDDEN:
                        mTextViewState.setText("Hidden");
                        break;
                    case BottomSheetBehavior.STATE_SETTLING:
                        mTextViewState.setText("Settling...");
                        break;
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                mTextViewState.setText("Sliding...");
            }
        });
    }
}

Leave a Comment