I will give you an example to explain the bottom sheet fragment template generated from android studio.

The result of this example is popping up a bottom sheet after click the button in the main activity.

Firstly, we can create the main activity as below witch a button to call the bottom sheet and a text view to show the result after clicking the item in the bottom sheet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ClickMe"
android:id="@+id/show_bottom_sheet"
app:layout_constraintBottom_toBottomOf="@+id/text_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="onShowBottomSheetClicked()"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Next, we generate the bottom sheet fragment template from android studio by clicking File -> New -> Fragment -> Modal Bottom Sheet

After click the Modal Bottom Sheet, android studio will automatically generate three files for you, show as below:

teampate_android_generated

  • ItemListDialogFragment: this is a java class which can render the recycler view and bottom sheet fragment.
  • fragment_item_list_dialog.xml: this is a layout of recycler view in the bottom sheet fragment (Also the layout of bottom sheet fragment) // you can change this file to change the layout of bottom sheet fragment.
  • fragment_item_list_dialog_item.xml: this is a view insert into the recycler view. // if you don’t use the recycler view, you can delete this file.

We don’t care the layout of the bottom sheet fragment, so we just keep the fragment_item_list_dialog.xml and fragment_item_list_dialog_item.xml. We will focus on the ItemListDialogFragment class.

Blow is the template of Modal Bottom Sheet Fragment, I will give you the explanation in the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package com.absolutelycold.bottomsheetfragment;

import android.content.Context;
import android.os.Bundle;

import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
* <p>A fragment that shows a list of items as a modal bottom sheet.</p>
* <p>You can show this modal bottom sheet from your activity like this:</p>
* <pre>
* ItemListDialogFragment.newInstance(30).show(getSupportFragmentManager(), "dialog");
* </pre>
* <p>You activity (or fragment) needs to implement {@link ItemListDialogFragment.Listener}.</p>
*/
public class ItemListDialogFragment extends BottomSheetDialogFragment {

// TODO: Customize parameter argument names
// the String to put and get arguments to/from bundle
private static final String ARG_ITEM_COUNT = "item_count";

//The listener to listen when the text view is clicked
private Listener mListener;

// TODO: Customize parameters
// Construstor and put arguments to fragment
public static ItemListDialogFragment newInstance(int itemCount) {
final ItemListDialogFragment fragment = new ItemListDialogFragment();
final Bundle args = new Bundle();
//the itemCount means the input data to the RecyclerView adapter, you can change it to
// String[] or ArrayList to bind the data to the recycler view
args.putInt(ARG_ITEM_COUNT, itemCount);
fragment.setArguments(args);
return fragment;
}


//onCreateView just render the recycler view in the fragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_item_list_dialog, container, false);
}


//onViewCreated: set the apdater and LayoutManager to recyclerview
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
final RecyclerView recyclerView = (RecyclerView) view;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new ItemAdapter(getArguments().getInt(ARG_ITEM_COUNT)));
}

// When attach to the parent, get the listener from parent
@Override
public void onAttach(Context context) {
super.onAttach(context);
final Fragment parent = getParentFragment();
if (parent != null) {
mListener = (Listener) parent;
} else {
mListener = (Listener) context;
}
}

//When close the application, clear the listener
@Override
public void onDetach() {
mListener = null;
super.onDetach();
}

//this is a listener pending to implement in the parent
public interface Listener {
void onItemClicked(int position);
}

// custom ViewHolder in the recycler view's adapter's onCreateViewHolder()
// and set listener to the item in the recycler view
private class ViewHolder extends RecyclerView.ViewHolder {

final TextView text;

ViewHolder(LayoutInflater inflater, ViewGroup parent) {
// TODO: Customize the item layout
super(inflater.inflate(R.layout.fragment_item_list_dialog_item, parent, false));
text = (TextView) itemView.findViewById(R.id.text);
text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
// When the item is clicked, the bottom sheet fragment disapear by
// calling dismiss()
dismiss();
}
}
});
}

}


//RecyclerView adapter
private class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {


private final int mItemCount;

//Recieve the data in the constructor
ItemAdapter(int itemCount) {
mItemCount = itemCount;
}

//Create the custom ViewHolder
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}

//Bind data to the ViewHolder
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(String.valueOf(position));
}


@Override
public int getItemCount() {
return mItemCount;
}

}

}

In this example, I will give a string array to the fragment, because we just want to show the finite options in the modal bottom sheet. And I will change the ItemListDialogFragment as below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package com.absolutelycold.bottomsheetfragment;

import android.content.Context;
import android.os.Bundle;

import androidx.annotation.Nullable;

import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
* <p>A fragment that shows a list of items as a modal bottom sheet.</p>
* <p>You can show this modal bottom sheet from your activity like this:</p>
* <pre>
* ItemListDialogFragment.newInstance(30).show(getSupportFragmentManager(), "dialog");
* </pre>
* <p>You activity (or fragment) needs to implement {@link ItemListDialogFragment.Listener}.</p>
*/
public class ItemListDialogFragment extends BottomSheetDialogFragment {

// TODO: Customize parameter argument names
private static final String ARG_OPTIONS_DATA = "options_data";
public static final String TAG = "ModalBottomSheetExample";
private Listener mListener;

// TODO: Customize parameters
public static ItemListDialogFragment newInstance(String[] optionsData) {
final ItemListDialogFragment fragment = new ItemListDialogFragment();
final Bundle args = new Bundle();
args.putStringArray(ARG_OPTIONS_DATA, optionsData);
fragment.setArguments(args);
return fragment;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_item_list_dialog, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
final RecyclerView recyclerView = (RecyclerView) view;
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new ItemAdapter(getArguments().getStringArray(ARG_OPTIONS_DATA)));
}

@Override
public void onAttach(Context context) {
super.onAttach(context);
final Fragment parent = getParentFragment();
if (parent != null) {
mListener = (Listener) parent;
} else {
mListener = (Listener) context;
}
}

@Override
public void onDetach() {
mListener = null;
super.onDetach();
}

public interface Listener {
void onItemClicked(int position);
}

private class ViewHolder extends RecyclerView.ViewHolder {

final TextView text;

ViewHolder(LayoutInflater inflater, ViewGroup parent) {
// TODO: Customize the item layout
super(inflater.inflate(R.layout.fragment_item_list_dialog_item, parent, false));
text = (TextView) itemView.findViewById(R.id.text);
text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onItemClicked(getAdapterPosition());
dismiss();
}
}
});
}

}

private class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {

private final String[] optionsData;

ItemAdapter(String[] optionsData) {
this.optionsData = optionsData;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(optionsData[position]);
}

@Override
public int getItemCount() {
return optionsData.length;
}

}

}

I change the input data as StringArray named options_data. At the same time, I change the apdater to give it the input StringArray.

Next, we need to implement the item listener in the parent(Main Activity). And show the fragment when button is clicked.

The code of MainActivity is shown as below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.absolutelycold.bottomsheetfragment;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements ItemListDialogFragment.Listener{

private TextView textView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text_view);
button = findViewById(R.id.show_bottom_sheet);
}

public void onShowBottomSheetClicked(View view) {
String positionsData[] = {"Open Browser", "Copy Url", "Open Other Application"};
ItemListDialogFragment.newInstance(positionsData).show(getSupportFragmentManager(), ItemListDialogFragment.TAG);
}

@Override
public void onItemClicked(int position) {
switch(position) {
case 0:
textView.setText("Open Browser is clicked");
break;
case 1:
textView.setText("Copy Url is clicked");
break;
case 2:
textView.setText("Open Other Application is clicked");
break;
default:
textView.setText("Opps, error");
}

}
}

结果如下:

Result

Download Code:

Download the project