Android

Working with Modal Bottom Sheets

Pinterest LinkedIn Tumblr

We have seen this UI component on Google maps, drive, or any other music player app. The Modal Bottom Sheet opens from the bottom of the screen and if the user clicks on the outside content then it dismisses from the screen.

Look at the demo first

Modal Bottom Sheet dialog demo

Let’s start the implementation of the demo.

1- Open the Android Studio and create a new project. Always select a blank template, if you’re working on the ProCodeGuru demo.

2- Open the build.gradle.xml file and enable the data binding feature. If you’re not familiar with DataBinding click here to read.

buildFeatures{
        dataBinding true
    }

Add below the dependencies in the build.gradle.xml file and sync Gradle now.

dependencies {

    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

3- Go to res->values and open the colors.xml file and add the below code

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="color_separator">#A8A7A7</color>
    <color name="bg_color">#212121</color>
</resources>

4- Open the strings.xml file and add the below code

<resources>
    <string name="app_name">ModalBottomSheetExample</string>


    <!-- App Strings -->
    <string name="str_tv">Modal Bottom Sheet Example</string>
    <string name="str_home">Home</string>
    <string name="str_fav">Favourite</string>
    <string name="str_jobs">Jobs</string>
    <string name="str_profile">Profile</string>
    <string name="tv_str_result">%s Clicked</string>
    <string name="str_btn">Display Sheet</string>
    <string name="str_lorem_ipsum">It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout</string>
</resources>

5- Go to res->layout and create a new resource file called fragment_bottom_modal_sheet.xml and add the below code. You can change a model sheet design according to your design requirements.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:background="@color/white"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/lnrHomeRow"
            android:layout_width="0dp"
            android:gravity="center_vertical"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_row"
            app:layout_constraintEnd_toEndOf="@+id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toTopOf="parent">

            <ImageView
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:src="@drawable/ic_home" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="@string/str_home"
                android:textColor="@color/bg_color"
                android:textSize="22sp" />
        </LinearLayout>

        <View
            android:id="@+id/viewHome"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:background="@drawable/bg_separator"
            app:layout_constraintEnd_toEndOf="@+id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toBottomOf="@+id/lnrHomeRow" />

        <LinearLayout
            android:id="@+id/lnrFavRow"
            android:gravity="center_vertical"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_row"
            app:layout_constraintEnd_toEndOf="@id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintBottom_toTopOf="@+id/viewFav"
            app:layout_constraintTop_toBottomOf="@+id/viewHome">

            <ImageView
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:src="@drawable/ic_fav" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="@string/str_fav"
                android:textColor="@color/bg_color"
                android:textSize="22sp" />
        </LinearLayout>


        <View
            android:id="@+id/viewFav"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:background="@drawable/bg_separator"
            app:layout_constraintEnd_toEndOf="@+id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toBottomOf="@+id/lnrFavRow" />

        <LinearLayout
            android:id="@+id/lnrJobsRow"
            android:layout_width="0dp"
            android:gravity="center_vertical"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_row"
            app:layout_constraintBottom_toBottomOf="@+id/viewJobs"
            app:layout_constraintEnd_toEndOf="@id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toBottomOf="@+id/viewFav">

            <ImageView
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:src="@drawable/ic_jobs" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="@string/str_jobs"
                android:textColor="@color/bg_color"
                android:textSize="22sp" />
        </LinearLayout>

        <View
            android:id="@+id/viewJobs"
            android:layout_width="0dp"
            android:layout_height="1dp"
            android:background="@drawable/bg_separator"
            app:layout_constraintEnd_toEndOf="@+id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toBottomOf="@+id/lnrJobsRow" />

        <LinearLayout
            android:id="@+id/lnrProfileRow"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_row"
            android:gravity="center_vertical"
            app:layout_constraintEnd_toEndOf="@id/rightGuideline"
            app:layout_constraintStart_toStartOf="@id/leftGuideline"
            app:layout_constraintTop_toBottomOf="@+id/viewJobs">

            <ImageView
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:src="@drawable/ic_profile" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="10dp"
                android:text="@string/str_profile"
                android:textColor="@color/bg_color"
                android:textSize="22sp" />
        </LinearLayout>

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/leftGuideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="20dp" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/rightGuideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="20dp" />


    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

6- Create a Java interface class called CallbackBottomSheet.java that will work as a callback.

package com.example.modalbottomsheetexample;

public interface CallbackBottomSheet {
    void onClickItem(String title);
}

7- Right-click on the package and create a new Java class called ModalBottomSheetFragment.java and add the below code.

package com.example.modalbottomsheetexample;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;

import com.example.modalbottomsheetexample.databinding.FragmentModalBottomSheetBinding;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

public class ModalBottomSheetFragment extends BottomSheetDialogFragment implements View.OnClickListener {
    private FragmentModalBottomSheetBinding binding;
    private CallbackBottomSheet callbackBottomSheet;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_modal_bottom_sheet, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initComponents();
    }

    /**
     * Apply listener on all the views.
     */
    private void initComponents() {
        binding.lnrHomeRow.setOnClickListener(this);
        binding.lnrFavRow.setOnClickListener(this);
        binding.lnrJobsRow.setOnClickListener(this);
        binding.lnrProfileRow.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.lnrHomeRow) {
            callbackBottomSheet.onClickItem(getString(R.string.str_home));
        } else if (v.getId() == R.id.lnrFavRow) {
            callbackBottomSheet.onClickItem(getString(R.string.str_fav));
        } else if (v.getId() == R.id.lnrJobsRow) {
            callbackBottomSheet.onClickItem(getString(R.string.str_jobs));
        } else if (v.getId() == R.id.lnrProfileRow) {
            callbackBottomSheet.onClickItem(getString(R.string.str_profile));
        }
        // TODO: 8/22/21 you can explore these conditions according to your project requirements
        dismiss();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        callbackBottomSheet = (MainActivity) context; // set callback with parent reference
    }
}

8- Open the MainActivity.java file and add the below code to display the Modal Bottom Sheet dialog. I added the comments for understanding the code. If you still have a problem displaying the Modal Bottom Sheet dialog, please put a comment below the post.

package com.example.modalbottomsheetexample;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Toast;


public class MainActivity extends AppCompatActivity implements CallbackBottomSheet {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * When user will click on the display button, then bottom sheet will display
     * @param v
     */
    public void displayModalBottomSheet(View v) {
        ModalBottomSheetFragment bottomSheetDialogFragment = new ModalBottomSheetFragment();
        bottomSheetDialogFragment.show(getSupportFragmentManager(), "Modal BottomSheet");
    }

    @Override
    public void onClickItem(String title) {
        Toast.makeText(this, String.format(getString(R.string.tv_str_result), title), Toast.LENGTH_SHORT).show();
    }
}

Thanks for reading the tutorial. Subscribe to my YouTube channel. Like and Share my Facebook page with your friends.

Write A Comment