DEV Community

Arnold Wafula
Arnold Wafula

Posted on โ€ข Originally published at Medium

1

Getting Started with Bottom Sheets in Android Using Kotlin Part 1 [Beginner Friendly]

Photo by [Jonathan Kemper](https://unsplash.com/de/@jupp?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/photos/t6Wmvbw_MdI?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
Hi guys ๐Ÿ‘‹, in this article, I'm going to delve into what a bottom sheet is, its common uses, and how it can be implemented in android development using Kotlin. I will cover its implementation in the traditional view system (XML-based).

Without further ado, we can ask ourselves the question. What is a bottom sheet?

According to Google's material.io documentation, a bottom sheet is a surface containing supplementary content that are anchored to the bottom of the screen and can be dismissed in order to interact with the underlying content.

Its use has been preferred over dialogs in recent years and as a smartphone user either on Android or iOS, you must have interacted with it. Personally an avid YouTube user, it is heavily and perfectly integrated within its U.I.

It is also worth noting that they are flexible and can hold a diverse range of information and layouts, including menu items, actions, and supplemental content.


There are two types of bottom sheets;

  1. Standard bottom sheet
  2. Modal bottom sheet

Standard Bottom Sheet

Also known as persistent bottom sheets, they co-exist with the screens main U.I and allow for simultaneous interaction with both the U.I and itself. It exists in the expanded, collapsed, and hidden states.

A good example of an app that utilizes the standard bottom sheet is Google Maps.
Standard Bottom sheet. Image courtesy of: https://m3.material.io/components/bottom-sheets

Modal Bottom Sheet

Strictly use on mobile devices, modal bottom sheets block interaction with the rest of the screen and serve as a perfect alternative to dialogs, as they provide more room and allow for the use of views such as Images and Text.
Modal bottom sheet. Image courtesy of: https://m3.material.io/components/bottom-sheets

In android development, they extend the BottomSheetDialogFragment class to provide functionalities such as behavior, and screen height among others. In this article, I am going to focus on the modal bottom sheets since they have a more popular use case compared to persistent bottom sheets.

If you wish to go straight into the source code, click the GitHub link below;

GitHub logo arnold-wafula / ModalBottomSheet-Medium

A small project that demonstrates the implementation of the modal bottom sheet in android. Written for my article on medium (Getting Started with Bottom Sheets in Android Using Kotlin [Beginner Friendly])

ModalBottomSheet-Medium

A simple android project that demonstrates the implementation of the modal bottom sheet in android. Written for my article on medium.

main_screen bottom_sheet_dialog

device-2023-02-03-193245.mp4




On Android Studio, Google's official IDE for Android development, navigate to File->New->New Project. Under the templates tab, choose Phone and Tablet and select Empty Activity. Let's start by creating the activity_main layout;

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<Button
android:id="@+id/btnModal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_modal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<Button
android:id="@+id/btnFullscreenModal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_fullscreen_modal"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnModal"/>
</androidx.constraintlayout.widget.ConstraintLayout>
view raw activity_main.xml hosted with โค by GitHub

Set up the MainActivity file by copy-pasting the code below;

MainActivity.kt

package com.lemonboy.modalbottomsheet
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import com.lemonboy.modalbottomsheet.databinding.ActivityMainBinding
import com.lemonboy.modalbottomsheet.dialog.FullscreenModalBottomSheetDialog
import com.lemonboy.modalbottomsheet.dialog.ModalBottomSheetDialog
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupModalButtons()
}
private fun setupModalButtons() {
binding.apply {
btnModal.setOnClickListener {
val modal = ModalBottomSheetDialog()
supportFragmentManager.let { modal.show(it, ModalBottomSheetDialog.TAG) }
}
btnFullscreenModal.setOnClickListener {
Snackbar.make(it, "Implementing on part 2", Snackbar.LENGTH_LONG).show()
}
}
}
}
view raw MainActivity.kt hosted with โค by GitHub

We will then define the layout for a single item containing an image and text that will appear in the modal bottom sheet. Create a new layout XML file item_bottomsheet and copy-paste the source code below;

item_bottomsheet.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/textShare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/share"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:fontFamily="@font/proxima_nova_scosf_condensed_light"/>
<ImageView
android:id="@+id/iconMail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/icon_mail"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@id/textShare"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/textMail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/mail"
android:textSize="16sp"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="@id/iconMail"
app:layout_constraintStart_toEndOf="@id/iconMail"
app:layout_constraintTop_toTopOf="@id/iconMail"
android:fontFamily="@font/proxima_nova_alt_light"/>
<ImageView
android:id="@+id/iconDuo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/icon_duo"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iconMail"/>
<TextView
android:id="@+id/textDuo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/duo"
android:textSize="16sp"
android:textColor="@color/black"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="@id/iconDuo"
app:layout_constraintStart_toEndOf="@id/iconDuo"
app:layout_constraintBottom_toBottomOf="@id/iconDuo"
android:fontFamily="@font/proxima_nova_alt_light"/>
<ImageView
android:id="@+id/iconSms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/icon_sms"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iconDuo"/>
<TextView
android:id="@+id/textSms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sms"
android:textSize="16sp"
android:textColor="@color/black"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="@id/iconSms"
app:layout_constraintStart_toEndOf="@id/iconSms"
app:layout_constraintBottom_toBottomOf="@id/iconSms"
android:fontFamily="@font/proxima_nova_alt_light"/>
<ImageView
android:id="@+id/iconYouTube"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/icon_youtube"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iconSms"/>
<TextView
android:id="@+id/textYoutube"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/youtube"
android:textSize="16sp"
android:textColor="@color/black"
app:layout_constraintTop_toTopOf="@id/iconYouTube"
android:fontFamily="@font/proxima_nova_alt_light"
app:layout_constraintStart_toEndOf="@id/iconYouTube"
app:layout_constraintBottom_toBottomOf="@+id/iconYouTube"/>
</androidx.constraintlayout.widget.ConstraintLayout>
view raw item_bottomsheet.xml hosted with โค by GitHub

Finally, the ModalBottomSheetDialog class displays the items defined in the item_bottomsheet.xml.

ModalBottomSheetDialog.kt

package com.lemonboy.modalbottomsheet.dialog
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.lemonboy.modalbottomsheet.databinding.ItemBottomsheetBinding
class ModalBottomSheetDialog : BottomSheetDialogFragment() {
private lateinit var binding : ItemBottomsheetBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = ItemBottomsheetBinding.inflate(inflater, container, false)
return binding.root
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// used to show the bottom sheet dialog
dialog?.setOnShowListener { it ->
val d = it as BottomSheetDialog
val bottomSheet = d.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
bottomSheet?.let {
val behavior = BottomSheetBehavior.from(it)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
}
}
return super.onCreateDialog(savedInstanceState)
}
companion object {
const val TAG = "ModalBottomSheetDialog"
}
}

Here is the final result;

Main screen with buttons to launch bottom sheets

bottom sheet displayed

So that is a simple way to build the modal bottom sheet in android. See you in part 2 of the article where I will dive into the fullscreen implementation of the same.

Peace โ˜ฎ๏ธโœŒ๏ธ

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, โ€œnot bad.โ€

Fixing code doesnโ€™t have to be the worst part of your day. Learn how Sentry can help.

Learn more

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. โค๏ธ