Currently, we are figuring how to implement such a bottom sheet, with the following requirements.
- Round corner bottom sheet.
- Fixed height bottom sheet.
- Non-draggable bottom sheet.
- Content in the bottom sheet is scrollable.
- Hide bottom sheet when we tap on non-bottom sheet item.
- Hide sheet when we press on back button.
- A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
We are considering, whether to use BottomSheetBehavior
or BottomSheetDialogFragment
.
So far, we manage to implement all the requirements, by using BottomSheetBehavior
.
Implementation using BottomSheetBehavior
However, we do not really like the solution as
- It increases the complexity of our
Activity
's layout, where additionalCoordinatorLayout
is required. - Manual touch event code handling is required at
Activity
, to achieve requirement 5, 6 & 7 (Hide bottom sheet).
Here's the code snippet by using BottomSheetBehavior
.
public class MainActivity extends AppCompatActivity {
private BottomSheetBehavior bottomSheetBehavior;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.image_button_0).setOnClickListener(view -> demo0());
findViewById(R.id.image_button_1).setOnClickListener(view -> demo1());
// 7) A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item
// will get focus and bottom sheet will hide.
findViewById(R.id.edit_text_0).setOnFocusChangeListener((view, b) -> {
if (b) {
hideBottomSheet();
}
});
// 7) A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item
// will get focus and bottom sheet will hide.
findViewById(R.id.edit_text_1).setOnFocusChangeListener((view, b) -> {
if (b) {
hideBottomSheet();
}
});
}
public void demo0() {
DemoBottomDialogFragment demoBottomDialogFragment = DemoBottomDialogFragment.newInstance();
demoBottomDialogFragment.show(getSupportFragmentManager(), "demoBottomDialogFragment");
}
public void demo1() {
// 1) Round corner bottom sheet.
View view = findViewById(R.id.bottom_sheet_layout_2);
/*
2) Fixed height bottom sheet.
3) Non-draggable bottom sheet.
4) Content in the bottom sheet is scrollable.
*/
this.bottomSheetBehavior = BottomSheetBehavior.from(view);
bottomSheetBehavior.setPeekHeight(900, true);
bottomSheetBehavior.setDraggable(false);
}
private boolean hideBottomSheet() {
if (this.bottomSheetBehavior != null) {
this.bottomSheetBehavior.setPeekHeight(0, true);
this.bottomSheetBehavior = null;
return true;
}
return false;
}
@Override
public void onBackPressed() {
// 5) Hide bottom sheet when we tap on non-bottom sheet item.
if (hideBottomSheet()) {
return;
}
super.onBackPressed();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 6) Hide sheet when we press on back button.
hideBottomSheet();
return super.onTouchEvent(event);
}
}
If we were using BottomSheetDialogFragment
, the code will be way more simpler. We can achieve all requirements, except number 7
- A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
Here's the outcome of BottomSheetDialogFragment
.
Implementation using BottomSheetDialogFragment
The good thing of using BottomSheetDialogFragment
is that,
- Will not increase the complexity of
Activity
's layout. - No code required at
Activity
, to hide the bottom sheet (Requirement 5, 6. Requirement 7 still not achievable)
Here's the code snippet.
public class DemoBottomDialogFragment extends BottomSheetDialogFragment {
public static DemoBottomDialogFragment newInstance() {
return new DemoBottomDialogFragment();
}
@NonNull
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
// https://stackoverflow.com/questions/58651661/how-to-set-max-height-in-bottomsheetdialogfragment
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override public void onShow(DialogInterface dialogInterface) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
// !!!
layoutParams.height = 900;
bottomSheet.setLayoutParams(layoutParams);
}
});
return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make the bottom sheet non drag-able.
setStyle(DialogFragment.STYLE_NORMAL, R.style.BottomSheetDialogStyle);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_layout, container,
false);
// get the views and attach the listener
return view;
}
}
I was wondering, if we were using BottomSheetDialogFragment
, is there a way to achieve
- A non-blocking bottom sheet. When we tap on non-bottom sheet item, the tapped item will get focus and bottom sheet will hide.
As you can see, when I tap on EditText
region, the bottom sheet is hidden. But, the EditText
is not getting focus.
Here's the complete workable demo for testing purpose - https://github.com/yccheok/wediary-sandbox/tree/master/bottom-sheet
Thank you.