In the previous example we learned about implement Model BottomSheet Dialog in Android, in this chapter we cover how to implement Persistent BottomSheet Dialog. Persistent Bottom Sheet dialogs provide additional content about the current screen. It is as a child of the CoordinatorLayout.
Let get started
Create Sample Project
Create a Project in Android studio (File->New->New Project) choose Empty Activity template and finish all basic setup Open xml file, you will see default TextView in the file Now drag and drop Text widget from Pallet window.
Update Root Element to CoordinatorLayout
Let replace ConstraintLayout file with Coordinator Layout file
Our xml file would be look like this
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.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=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Persistent BottomSheet Dialog" android:textSize="28sp" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> |
Create UI for BottomSheetDialog
So let create a simple layout file
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/lnr_bottomsheet" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_height="wrap_content" android:background="#F4D595" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" app:behavior_hideable="false" app:behavior_peekHeight="72dp" android:padding="16sp"> <LinearLayout android:layout_width="match_parent" android:orientation="horizontal" android:gravity="center_vertical" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_weight="1" android:layout_height="wrap_content" android:text="Dr. Rags" android:textSize="20sp" android:textColor="@color/black" android:layout_marginBottom="5dp" android:textStyle="bold" /> <ImageView android:id="@+id/img_slid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/arrow_up_24" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Friday, December 22" android:textSize="14sp" android:layout_marginBottom="5dp" android:textStyle="bold" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#FFFFFF"/> <LinearLayout android:id="@+id/lnr_edit" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_marginTop="18dp" android:layout_height="wrap_content"> <ImageView android:layout_width="28dp" android:layout_height="28dp" app:tint="@color/black" android:src="@android:drawable/ic_menu_edit" /> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:layout_marginLeft="12dp" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Edit" android:textColor="@color/black" android:textSize="20sp" android:layout_marginBottom="5dp" android:textStyle="bold" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Edit event details" android:textSize="14sp" android:textColor="#5A503C" android:layout_marginBottom="5dp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/lnr_pay" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_marginTop="18dp" android:layout_height="wrap_content"> <ImageView android:layout_width="28dp" android:layout_height="28dp" app:tint="@color/black" android:src="@android:drawable/stat_notify_more" /> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:layout_marginLeft="12dp" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Payment" android:textSize="20sp" android:textColor="@color/black" android:layout_marginBottom="5dp" android:textStyle="bold" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="add a payment" android:textSize="14sp" android:textColor="#5A503C" android:layout_marginBottom="5dp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/lnr_cancel" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_marginTop="18dp" android:layout_height="wrap_content"> <ImageView android:layout_width="28dp" android:layout_height="28dp" app:tint="@color/black" android:src="@android:drawable/ic_menu_close_clear_cancel" /> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:layout_marginLeft="12dp" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Cancel" android:textSize="20sp" android:textColor="@color/black" android:layout_marginBottom="5dp" android:textStyle="bold" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Cancel payment" android:textSize="14sp" android:textColor="#5A503C" android:layout_marginBottom="5dp" android:textStyle="bold" /> </LinearLayout> </LinearLayout> </LinearLayout>
|
Add Bottom Sheet behavioral to the layout file
We have done with our BottomSheet Dialog UI, now lets add BottomSheetBehaviour to root element of the layout file to act as Bottomsheet Dialog.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_height="wrap_content" android:background="#F4D595" app:behavior_hideable="false" app:behavior_peekHeight="72dp" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" android:padding="16sp"></LinearLayout> |
The Bottom Sheet behavioral flags include
app:layout_behavior
- The class name of a Behavior class defining special runtime behavior for this child view. This applies the BottomSheetBehavior
into the XML file. It is the most important BottomSheetBehavior
attribute since it defines a given layout as a Bottom Sheet dialog.
app:behavior_hideable
- takes a Boolean value. If true
, a user can drag and hide the dialog by sliding it down. If false, the dialog will float on the screen and will not make it to hidden.
app:behavior_peekHeight
- it defines the height of the Bottom Sheet visible to the user
Note : To apply BottomSheet Behavior to any layout, it must be a child of CoordinatorLayout
Include layout inside the MainActivity xml file
After including the BottomSheet Behavior layout file to xml, it would be like below
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.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=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Persistent BottomSheet Dialog" android:textSize="28sp" /> <include layout="@layout/dialog_layout" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> |
Now deploy the application on real device/emulator
![]() |
Add Expand Collapse Animation to BottomSheet
To apply slide up and collapse animations to the Bottomsheet we need to apply several states to it. The Bottom Sheet has several states which we need to understand
STATE_EXPANDED
- the dialog is visible to its maximum defined height.STATE_COLLAPSED
- the dialog is visible depending on the set peekHeight
.STATE_DRAGGING
- the user is dragging the dialog up and down.STATE_SETTLING
- show that the dialog is settling at a specific height. This can be the peekHeight
, expanded height, or zero if the dialog is hidden.STATE_HIDDEN
- the dialog is not visible.
img_slid.setOnClickListener(View.OnClickListener { if (sheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) { sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED) } else { sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED) } }) |
Add BottomSheetCallback
To handle the BottomSheet state we need to implement BottomSheetCallback
val liner_bottomsheet=findViewById<LinearLayout>(R.id.lnr_bottomsheet) val sheetBehavior = BottomSheetBehavior.from(liner_bottomsheet); sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { } override fun onSlide(bottomSheet: View, slideOffset: Float) { } }) |
![]() |
Enable/Disable BottomSheet Drag feature
We can enable/disable drag feature of the Bottomsheet by isDraggable property
sheetBehavior.isDraggable=true |
Complete code for Persistent Bottomsheet Dialog
MainActivity.kt file
package com.example.persistentbottomsheet import android.os.Bundle import android.view.View import android.widget.ImageView import android.widget.LinearLayout import androidx.appcompat.app.AppCompatActivity import com.google.android.material.bottomsheet.BottomSheetBehavior class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val liner_bottomsheet=findViewById<LinearLayout>(R.id.lnr_bottomsheet) val img_slid=findViewById<ImageView>(R.id.img_slid) val sheetBehavior = BottomSheetBehavior.from(liner_bottomsheet); img_slid.setOnClickListener(View.OnClickListener { if (sheetBehavior.state != BottomSheetBehavior.STATE_EXPANDED) { sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED) } else { sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED) } }) sheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { } override fun onSlide(bottomSheet: View, slideOffset: Float) { img_slid.setRotation(slideOffset * 180); } }) } } |
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.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=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Persistent BottomSheet Dialog" android:textSize="28sp" /> <include layout="@layout/dialog_layout" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> |
Conclusion: Android Bottom Sheet dialog is a unique way to display UI content on the current screen. It provides more room to include content.