
Bottom Sheet Navigation in Android App Development using Kotlin: A Complete Guide
The Bottom Sheet Navigation is an increasingly popular UI component in modern Android apps. It slides up from the bottom of the screen and provides an easy way to access different app sections, actions, or contextual information. It’s commonly used in Material Design and is effective for giving users quick access to secondary screens without navigating away from the main content.
In this guide, we’ll explore how to implement Bottom Sheet Navigation in an Android app using Kotlin.
What is Bottom Sheet Navigation?
A Bottom Sheet Navigation is a sliding panel that appears from the bottom of the screen, displaying navigation options. It can be a modal or a persistent bottom sheet:
- Modal Bottom Sheet: Appears temporarily as an overlay on top of other content and can be dismissed.
- Persistent Bottom Sheet: Stays anchored at the bottom and is part of the main UI.
Android provides built-in support for bottom sheets with BottomSheetDialogFragment
for modal sheets and BottomSheetBehavior
for persistent sheets.
Prerequisites
To start, make sure you have:
- Android Studio (latest version).
- Material Components Library in your project’s dependencies, as it includes support for bottom sheets and other Material Design components.
Add the Material Components library to your build.gradle
file in the dependencies
section:
implementation 'com.google.android.material:material:<version>'
Replace <version>
with the latest version available.
Step 1: Create a New Project
- Open Android Studio.
- Create a new project using the Empty Activity template.
- Choose Kotlin as the programming language.
Step 2: Design the Bottom Sheet Layout
Create a new layout file for the bottom sheet in res/layout
. We’ll call this layout bottom_sheet_navigation.xml
.
bottom_sheet_navigation.xml:
<?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="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/bottom_sheet_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bottom Sheet Navigation"
android:textSize="18sp"
android:textStyle="bold"
android:gravity="center"
android:paddingBottom="16dp"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Home"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_profile"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Profile"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Settings"/>
</LinearLayout>
This layout defines a simple vertical list of navigation items (buttons) in a bottom sheet.
Step 3: Create a BottomSheetDialogFragment Class
To display the bottom sheet, create a new Kotlin class called BottomNavigationDrawerFragment
. This class will extend BottomSheetDialogFragment
, which gives us a pre-configured modal bottom sheet.
BottomNavigationDrawerFragment.kt:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.bottom_sheet_navigation.*
class BottomNavigationDrawerFragment : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.bottom_sheet_navigation, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Set up click listeners for each button in the bottom sheet
btn_home.setOnClickListener {
// Navigate to Home
// Handle the navigation action here
dismiss() // Close the bottom sheet after selection
}
btn_profile.setOnClickListener {
// Navigate to Profile
dismiss()
}
btn_settings.setOnClickListener {
// Navigate to Settings
dismiss()
}
}
}
In this class:
- We override
onCreateView
to inflate thebottom_sheet_navigation.xml
layout. - In
onViewCreated
, we set up click listeners for each button to handle navigation.
Step 4: Launch the Bottom Sheet from MainActivity
In MainActivity
, we’ll create a button or a toolbar icon that opens the bottom sheet when clicked.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_show_bottom_sheet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Open Bottom Navigation"
android:layout_centerInParent="true"/>
</RelativeLayout>
MainActivity.kt:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Show bottom sheet when the button is clicked
btn_show_bottom_sheet.setOnClickListener {
val bottomSheetFragment = BottomNavigationDrawerFragment()
bottomSheetFragment.show(supportFragmentManager, bottomSheetFragment.tag)
}
}
}
In MainActivity
, we set up a click listener on the button to display the BottomNavigationDrawerFragment
.
Step 5: Create Fragment Classes for Each Destination
For each navigation destination, create a fragment class. We’ll create HomeFragment
, ProfileFragment
, and SettingsFragment
.
Example: HomeFragment.kt:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class HomeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
}
Repeat this for ProfileFragment
and SettingsFragment
. Create corresponding layout files (fragment_home.xml
, fragment_profile.xml
, and fragment_settings.xml
) in the res/layout
directory.
Step 6: Handle Fragment Transactions in MainActivity
In BottomNavigationDrawerFragment
, we need to replace the container’s content in MainActivity
based on the user’s selection in the bottom sheet. Add fragment transaction handling code to replace the fragment in MainActivity
.
Update BottomNavigationDrawerFragment
as follows:
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.bottom_sheet_navigation.*
class BottomNavigationDrawerFragment : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.bottom_sheet_navigation, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Handle each navigation option
btn_home.setOnClickListener {
openFragment(HomeFragment())
dismiss()
}
btn_profile.setOnClickListener {
openFragment(ProfileFragment())
dismiss()
}
btn_settings.setOnClickListener {
openFragment(SettingsFragment())
dismiss()
}
}
private fun openFragment(fragment: Fragment) {
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.fragment_container, fragment)
?.addToBackStack(null)
?.commit()
}
}
In this version, openFragment
takes a Fragment
parameter and performs a fragment transaction in the MainActivity
to display the selected fragment.
Step 7: Run the Application
Build and run the app on an emulator or physical device. You should see:
- A button on the main screen to open the bottom sheet.
- When you tap on the button, the bottom sheet navigation menu slides up from the bottom.
- Tapping any button in the bottom sheet (Home, Profile, Settings) loads the corresponding fragment in the main content area.
Additional Tips
- Customizing the Bottom Sheet: You can further customize the appearance and behavior of the bottom sheet by setting properties in
BottomSheetDialogFragment
. - Adding Animations: Android’s
Transition
framework allows you to add custom animations when switching between fragments. - Using BottomSheetBehavior: For a persistent bottom sheet that remains visible, consider using
BottomSheetBehavior
to anchor it within the main content layout.
Conclusion
Implementing a bottom sheet navigation panel provides a user-friendly, visually appealing way to
allow navigation within your Android app. Using Kotlin and Material Components, you can easily integrate a bottom sheet for various navigation options while keeping the interface minimal and functional. With further customization and animations, you can refine the bottom sheet to create an engaging, high-quality user experience.
Happy coding!