Material Design Android Bottom Sheet Tutorial with Example in Kotlin
Android Bottom Sheet is a component that slides up from the bottom to up in an application.
For example, when you have a video to share and you click on the Share button, it will open a one slider from bottom, which contains available apps in your device.
Sometimes it can also have a menu option. In a simple word, the Android Bottom sheet is an area (surface) that containing extra useful content at the bottom of the screen. It’s hidden in the bottom or partial show to the user will be shown to the user on the action.
In this tutorial, you will learn the following:
- What is Android Bottom Sheet and it’s type
- Example and code of Bottom sheet.
- Standard bottom sheets: Display content that complements the screen’s primary content. Remain visible screen users can interact with the primary content. Like, google maps are shown at the bottom how much time and km etc detail of the destination from your point. Here user can interact with both the bottom sheet and the remain of screen content.
- Modal bottom sheets: This can be an alternative to inline menus or simple dialogs on mobile, providing room for additional items, longer descriptions, and iconography. They must be dismissed in order to interact with the underlying content. Example share the location in Google Maps.
- STATE_COLLAPSED: The bottom sheet is visible but only showing its peek height. This state is usually the ‘resting position’ of a Bottom Sheet
- STATE_EXPANDED: The bottom sheet is visible and its maximum height and it is neither dragging or settling.
- STATE_DRAGGING: The user is actively dragging the bottom sheet up or down.
- STATE_SETTLING: The bottom sheet is settling to specific height after a drag/swipe gesture. This will be the peek height, expanded height, or 0, in case the user action caused the bottom sheet to hide.
- STATE_HIDDEN: The bottom sheet is no longer visible.
- res/ layout / bottom_sheet.xml
- Create “bottom_sheet.xml” and Add code
<?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"
android:id="@+id/parent_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.core.widget.NestedScrollView
android:id="@+id/nested_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/grey_3"
android:scrollbars="none"
android:scrollingCache="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="@dimen/spacing_smlarge"
android:paddingRight="@dimen/spacing_smlarge"
android:text="@string/lorem_ipsum"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/grey_90" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_large"
android:clickable="true"
android:gravity="center"
android:tint="@color/purple_500"
app:backgroundTint="@android:color/white"
app:fabSize="normal"
app:layout_anchor="@id/bottom_sheet"
app:layout_anchorGravity="end"
app:rippleColor="@color/grey_40"
android:id="@+id/btnCode"
app:srcCompat="@drawable/baseline_directions_24" />
<FrameLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
app:behavior_fitToContents="false"
app:behavior_hideable="false"
app:behavior_peekHeight="300dp"
app:behavior_skipCollapsed="true"
app:layout_behavior="@string/bottom_sheet_behavior">
<LinearLayout
android:id="@+id/player_control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/lyt_sheet_header"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="@color/indigo_500"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/spacing_mlarge">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Starbucks Valencia"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@android:color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Coffee Shop"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="@color/grey_10" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_large"
android:text="15 min"
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
android:textColor="@color/grey_10" />
</LinearLayout>
<LinearLayout
android:id="@+id/lyt_sheet_header_white"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<ImageView
android:id="@+id/bt_expand"
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:padding="15dp"
app:srcCompat="@drawable/ic_expand_arrow"
app:tint="@color/grey_80" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Starbucks Valencia"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/grey_80" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/grey_5" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:paddingHorizontal="?attr/actionBarSize"
android:paddingVertical="@dimen/spacing_large">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/spacing_mxlarge"
android:layout_height="@dimen/spacing_mxlarge"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
app:srcCompat="@drawable/ic_phone"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:text="CALL"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/purple_500"
android:textStyle="bold" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/spacing_mxlarge"
android:layout_height="@dimen/spacing_mxlarge"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
app:srcCompat="@drawable/ic_launch"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:text="WEBSITE"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/purple_500"
android:textStyle="bold" />
</LinearLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="@dimen/spacing_mxlarge"
android:layout_height="@dimen/spacing_mxlarge"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
app:srcCompat="@drawable/ic_add_circle_outline"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium"
android:text="SAVE"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/purple_500"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/grey_5" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/spacing_middle" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:padding="15dp"
app:srcCompat="@drawable/ic_location"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="740 Valencia St, San Francisco, CA"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/grey_80" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:padding="15dp"
app:srcCompat="@drawable/ic_phone"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(415) 349-0942"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/grey_80" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:padding="15dp"
app:srcCompat="@drawable/ic_schedule"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wed, 10 AM - 9 PM"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/grey_80" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:padding="15dp"
app:srcCompat="@drawable/ic_book"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Menu"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/grey_80" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="?attr/actionBarSize"
android:layout_height="?attr/actionBarSize"
android:padding="15dp"
app:srcCompat="@drawable/ic_label"
app:tint="@color/purple_500" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add Label"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textColor="@color/grey_80" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/spacing_middle" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/grey_5" />
<TextView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="center_vertical"
android:paddingLeft="@dimen/spacing_smlarge"
android:paddingRight="@dimen/spacing_smlarge"
android:text="PHOTOS"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@color/grey_80"
android:textStyle="bold" />
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/spacing_smlarge"
android:layout_marginRight="@dimen/spacing_smlarge"
android:scrollbarSize="2dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/image_1"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginRight="@dimen/spacing_medium"
android:scaleType="centerCrop"
android:src="@color/grey_20" />
<ImageView
android:id="@+id/image_2"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginRight="@dimen/spacing_medium"
android:scaleType="centerCrop"
android:src="@color/grey_20" />
<ImageView
android:id="@+id/image_3"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginRight="@dimen/spacing_medium"
android:scaleType="centerCrop"
android:src="@color/grey_20" />
<ImageView
android:id="@+id/image_4"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginRight="@dimen/spacing_medium"
android:scaleType="centerCrop"
android:src="@color/grey_20" />
<ImageView
android:id="@+id/image_5"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginEnd="@dimen/spacing_medium"
android:layout_marginRight="@dimen/spacing_medium"
android:scaleType="centerCrop"
android:src="@color/grey_20" />
</LinearLayout>
</HorizontalScrollView>
<View
android:layout_width="match_parent"
android:layout_height="@dimen/spacing_middle" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/grey_5" />
<TextView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="center_vertical"
android:paddingLeft="@dimen/spacing_smlarge"
android:paddingRight="@dimen/spacing_smlarge"
android:text="DESCRIPTION"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:textColor="@color/grey_80"
android:textStyle="bold" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="@dimen/spacing_smlarge"
android:paddingRight="@dimen/spacing_smlarge"
android:text="@string/very_long_lorem_ipsum_2"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="@color/grey_90" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical"
android:paddingVertical="@dimen/spacing_middle">
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
package com.boltuix.bottomsheet
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.boltuix.bottomsheet.databinding.BottomSheetBinding
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
class BottomSheetFragment : Fragment() {
private var _binding: BottomSheetBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
_binding = BottomSheetBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//......................................................
val mBehavior = BottomSheetBehavior.from<View>(binding.bottomSheet)
mBehavior.addBottomSheetCallback(object : BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
mBehavior.isDraggable = false
binding.lytSheetHeader.visibility = View.GONE
binding.lytSheetHeaderWhite.visibility = View.VISIBLE
} else {
mBehavior.isDraggable = true
binding.lytSheetHeader.visibility = View.VISIBLE
binding.lytSheetHeaderWhite.visibility = View.GONE
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
binding.btExpand.setOnClickListener(View.OnClickListener {
mBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED)
})
//......................................................
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Is there an example implementation of this BottomSheet in Jetpack Compose?
ReplyDelete