The Bottom Sheet is seen in many applications such as Google Drive, and Google Maps and most of the applications used the Bottom Sheet to display the data inside the application. In this article, we will take a look at implementing a Bottom Sheet in the Android app using Kotlin in Android Studio.
What is Bottom Sheet?
Bottom Sheet is a component of the Android design support library that is used to display different actions in an expandable UI design. It is an expandable widget that opens from the bottom of the android device on clicking on a specific Button or View.
Types of Bottom Sheet?
There are two different types of Bottom Sheets as
- Persistent Bottom Sheet and
- Modal Bottom Sheet
Persistent Bottom Sheet
A Persistent Bottom Sheet will be displayed on the bottom of the screen in our Android application. This sheet will be displayed at the bottom of the screen making some portion of the content visible. The elevation of this bottom sheet is the same as that of the app. Users can be able to navigate to both the app along with the bottom sheet at a time. Below is the example for the Persistent Bottom Sheet.
Modal Bottom Sheet
Modal Bottom Sheet will also be displayed on the bottom of the screen, but the difference is the user will not be able to use the app’s background content when the bottom sheet is open. This type of bottom sheet is having an elevation slightly higher than that of the app. When this bottom sheet is open user will not be able to access the app’s content. Users can at a time use the bottom sheet or the app’s content. Below is the example for the Modal Bottom Sheet.
What we are going to build in this article?
A sample video is given below to get an idea about what we are going to do in this article.
Step by Step Implementation
Step 1: Create a New Project in Android Studio
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
Step 2: Create Your Model class ItemViewModel.kt
data class ItemViewModel(val image: Int, val text: String) {
} |
Step 3: Create Your Adapter & CardView Item
Create YourAdapter.kt & cardview_item.xml
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class YourAdapter( private val mList: ArrayList<ItemViewModel>) :
RecyclerView.Adapter<YourAdapter.ViewHolder>() {
var onItemClick : ((ItemViewModel) -> Unit)? = null
// create new views
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// inflates the card_view_design view
// that is used to hold list item
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.cardview_item, parent, false )
return ViewHolder(view)
}
// binds the list items to a view
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val itemsViewModel = mList[position]
holder.imageView.setImageResource(itemsViewModel.image)
holder.textView.text = itemsViewModel.text
holder.itemView.setOnClickListener(){
onItemClick?.invoke(itemsViewModel)
}
}
// return the number of the items in the list
override fun getItemCount(): Int {
return mList.size
}
// Holds the views for adding it to image and text
class ViewHolder(ItemView: View) :
RecyclerView.ViewHolder(ItemView) {
val imageView: ImageView = itemView.findViewById(R.id.iv_scheme)
val textView: TextView = itemView.findViewById(R.id.tv_scheme)
// val ll: LinearLayout = itemView.findViewById(R.id.cv_scheme)
}
} |
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.cardview.widget.CardView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "10dp"
app:cardElevation = "6dp" >
< LinearLayout
android:id = "@+id/cv_scheme"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal"
android:padding = "5dp" >
< ImageView
android:id = "@+id/iv_scheme"
android:layout_width = "40dp"
android:layout_height = "40dp"
android:layout_gravity = "center"
android:background = "@drawable/ic_calendar" />
< LinearLayout
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:orientation = "vertical"
android:padding = "5dp" >
< TextView
android:id = "@+id/tv_scheme"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "10dp"
android:layout_marginLeft = "15dp"
android:textColor = "@color/green"
android:text = "Schemes"
android:textSize = "20sp"
android:textStyle = "bold" />
< TextView
android:id = "@+id/tv_disc"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "10dp"
android:layout_marginLeft = "15dp"
android:text = "Discription test test"
android:textSize = "20sp" />
</ LinearLayout >
< TextView
android:id = "@+id/tv_dt_time"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginTop = "10dp"
android:layout_marginStart = "10dp"
android:layout_marginLeft = "15dp"
android:text = "17-06-2022"
android:textSize = "15sp" />
</ LinearLayout >
</ androidx.cardview.widget.CardView >
|
Step 4: Create Recyclerview & BottomSheet
Then in your MainActivity call your onItemClick
package <your-Package-name>
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import com.luezoid.vaw.adapters.YourAdapter
import com.luezoid.vaw.data.model.models.calendar.ItemViewModel
class MainActivity : AppCompatActivity() {
private lateinit var yourAdapter: YourAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// getting the recyclerview by its id
val recyclerview = findViewById<RecyclerView>(R.id.cal_rv)
val cardView = findViewById<Button>(R.id.btn_submit)
// this creates a vertical layout Manager
recyclerview.layoutManager = LinearLayoutManager( this )
recyclerview.setHasFixedSize( true )
// ArrayList of class ItemsViewModel
val data = ArrayList<ItemViewModel>()
// This loop will create 20 Views containing
// the image with the count of view
for (i in 1 .. 20 ) {
data.add(ItemViewModel(R.drawable.ic_calendar, "Scheme " + i))
}
// var adapter = CalendarAdapter(data)
yourAdapter = YourAdapter(data)
// This will pass the ArrayList to our Adapter
var adapter = calViewAdapter
// Setting the Adapter with the recyclerview
recyclerview.adapter = adapter
calViewAdapter.onItemClick = {
val dialog = BottomSheetDialog( this )
val view = layoutInflater.inflate(R.layout.cal_bottomsheet, null )
val btnClose = view.findViewById<Button>(R.id.btn_submit)
btnClose.setOnClickListener {
dialog.dismiss()
}
dialog.setCancelable( true )
dialog.setCanceledOnTouchOutside( true )
dialog.setContentView(view)
dialog.show()
Toast.makeText( this @MainActivity , "Item clicked " , Toast.LENGTH_SHORT).show()
}
}
} |
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = ".MainActivity" >
< androidx.recyclerview.widget.RecyclerView
android:id = "@+id/cal_rv"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:visibility = "visible"
tools:listitem = "@layout/calendar_cardview" />
</ LinearLayout >
|
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:background = "#ffffff"
android:orientation = "vertical"
app:layout_behavior = "android.support.design.widget.BottomSheetBehavior" >
< LinearLayout
android:id = "@+id/fragment_history_bottom_sheet_edit"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:clickable = "true"
android:focusable = "true"
android:foreground = "?android:attr/selectableItemBackground"
android:orientation = "horizontal"
android:padding = "16dp" >
< TextView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_gravity = "center"
android:text = "Remark"
android:textSize = "20dp"
android:textStyle = "bold" />
</ LinearLayout >
< LinearLayout
android:id = "@+id/fragment_history_bottom_sheet_delete"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:clickable = "true"
android:focusable = "true"
android:foreground = "?android:attr/selectableItemBackground"
android:orientation = "horizontal"
android:padding = "16dp" >
< EditText
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:inputType = "textMultiLine"
android:layout_gravity = "center"
android:hint = "Enter Remark" />
</ LinearLayout >
< Button
android:id = "@+id/btn_submit"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:layout_gravity = "center"
android:layout_marginLeft = "20dp"
android:layout_marginRight = "20dp"
android:layout_marginBottom = "10dp"
android:hint = "Submit"
android:textStyle = "bold"
android:textColor = "@color/white" />
</ LinearLayout >
|
Output: