Hey Guys I recently used Bottom sheets, so that I should write a blog about it because I don’t see a lot of developers using this in their app UI’s.
It’s a very interesting UI element. A Bottom Sheet is a sheet of material that slides up from the bottom edge of the screen. Displayed only as a result of a user-initiated action, and can be swiped up to reveal additional content. It can be a temporary modal surface or a persistent structural element of an app.
This component was introduced in the Android Design Support library 23.2. Many apps like Google Maps use the bottom sheet, in which a sliding window pops up from the bottom of the screen. Also the Google play music app uses. When we drag up the sheet we see the song details as well as the current playlist.
There are 3 states of Bottom sheets :-
- Expanded — When the sheet is completely visible.
- Collapsed — When the sheet is partially visible.
- Hidden — When the sheet is completely hidden.
Step 1 is we need to import the latest design support library. Put this line in your app level build.gradle file.
compile ‘com.android.support:design:23.2.0’
Then one should create a new Blank Activity (not Empty Activity) in Android Studio. It sets up the CoordinatorLayout by default.
So now there ate two layouts created by default namely activity_main.xml and content_main.xml.
<?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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="yet.best.bottomsheets.MainActivity" tools:showIn="@layout/activity_main"> <Button android:id="@+id/open" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_margin="5dp" android:text="Open Bottom Sheet" /> <Button android:id="@+id/collapse" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/open" android:layout_centerHorizontal="true" android:layout_margin="5dp" android:text="Collapse Bottom Sheet" /> <Button android:id="@+id/hide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/collapse" android:layout_centerHorizontal="true" android:layout_margin="5dp" android:text="Hide Bottom Sheet" /> </RelativeLayout>
Notice that 3 Buttons have been created in this layout to perform different actions with the bottom sheets.
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" android:fitsSystemWindows="true" tools:context="yet.best.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> <include layout="@layout/content_main" /> <include android:id="@+id/bottom_sheet" layout="@layout/bottomsheet_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" app:layout_anchor="@id/bottom_sheet" app:layout_anchorGravity="top|right|end" /> </android.support.design.widget.CoordinatorLayout>
Those who aren’t familiar with the coordinator layout — basically there is a base level layout activity_main which contains the FloatingButton and within this layout including content_main.xml which will contain the rest of the layout. Notice that one also has to include bottomsheet_main.xml. This layout contains our bottom sheet layout which will be created next.
Create a new layout file called bottomsheet_main.xml
bottomsheet_main.xml
<?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:layout_width="match_parent" android:layout_height="300dp" android:background="#d3d3d3" app:behavior_hideable="true" app:behavior_peekHeight="70dp" app:layout_behavior="@string/bottom_sheet_behavior"> <TextView android:id="@+id/heading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="7dp" android:text="Collapsed" android:textSize="18sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="Main Content" android:textSize="20sp" /> </RelativeLayout>
This layout is how our bottom sheet will actually look. You can design it as you want.
Now for the actual java code. This is the easiest part actually. Just set listeners to the 3 buttons created and perform the corresponding action with the bottom sheet.
public class MainActivity extends AppCompatActivity { BottomSheetBehavior bottomSheetBehavior; Button open, collapse, hide; TextView heading; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); View bottomSheet = findViewById(R.id.bottom_sheet); bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet); setup(); } private void setup() { open = (Button) findViewById(R.id.open); collapse = (Button) findViewById(R.id.collapse); hide = (Button) findViewById(R.id.hide); heading = (TextView) findViewById(R.id.heading); //Handling movement of bottom sheets from buttons open.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); heading.setText("Welcome"); heading.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary)); } }); collapse.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); heading.setText("Collapsed"); heading.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent)); } }); hide.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); } }); //Handling movement of bottom sheets from sliding bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(View bottomSheet, int newState) { if (newState == BottomSheetBehavior.STATE_COLLAPSED) { heading.setText("Collapsed"); heading.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent)); } else if (newState == BottomSheetBehavior.STATE_EXPANDED) { heading.setText("Welcome"); heading.setTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary)); } } @Override public void onSlide(View bottomSheet, float slideOffset) {} }); } }
We just use the bottomSheetBehavior.setState() method to set the relevant state on each button click.
The bottom sheets can also be dragged by touch gestures. One can simply touch the sheet and drag them up or down. For these touch gestures to be handled one has to implement the onStateChanged() listener. This listener is fired everytime the state of the sheet changes by gestures. Whenever this triggers it checks the state of the bottom sheet and again do the desired action which user would have done by the button clicks.
As you can see, this is a pretty neat UI solution and can be implemented so easily. Go try it out for yourself. Adios!