タイトルのような実装を行う機会がたまにあるのですが、毎回やり方が分からなくなっている気がするので、メモとして残しておきます。
結論から言うと、以下の対応をソースコード上で行うことによって実現できます。
BottomSheetDialog
のコンテンツ表示部分のlayout_height
にmatch_parent
を指定するBottomSheetBehavior
のpeekHeight
を画面の縦幅と一致させる
具体的には以下のようになります。
class FullScreenBottomSheetDialogFragment : BottomSheetDialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val view = View.inflate(requireContext(), R.layout.fragment_full_screen_dialog, null) return super.onCreateDialog(savedInstanceState).apply { setContentView(view) setOnShowListener { val bottomSheetDialog = (it as? BottomSheetDialog) ?: return@setOnShowListener val bottomSheet = bottomSheetDialog.findViewById<FrameLayout>(R.id.design_bottom_sheet) ?: return@setOnShowListener // 1. BottomSheetDialogのコンテンツ表示部分のlayout_heightにmatch_parentを指定する bottomSheet.layoutParams.height = FrameLayout.LayoutParams.MATCH_PARENT // 2. BottomSheetBehaviorのpeekHeightを画面の縦幅と一致させる val screenHeight = Resources.getSystem().displayMetrics.heightPixels BottomSheetBehavior.from(bottomSheet).peekHeight = screenHeight } } } ... }
ここからは、BottomSheet周辺の実装を追っていきます。
まず、1.の「BottomSheetDialog
のコンテンツ表示部分のlayout_height
にmatch_parent
を指定する」に関連する実装を見ていきます。
BottomSheetDialogFragment#onCreateDialog()
を呼び出すとBottomSheetDialog
オブジェクトが返却されます。*1
@NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { return new BottomSheetDialog(getContext(), getTheme()); }
BottomSheetDialog#setContentView()
の中でwrapInBottomSheet()
が呼ばれ、その中でensureContainerAndBehavior()
が呼ばれます。*2
ensureContainerAndBehavior()
ではdesign_buttom_sheet_dialog
の中のdesign_bottom_sheet
へBottomSheetBehavior
をセットする処理が行われます。
private FrameLayout ensureContainerAndBehavior() { if (container == null) { container = (FrameLayout) View.inflate(getContext(), R.layout.design_bottom_sheet_dialog, null); coordinator = (CoordinatorLayout) container.findViewById(R.id.coordinator); bottomSheet = (FrameLayout) container.findViewById(R.id.design_bottom_sheet); behavior = BottomSheetBehavior.from(bottomSheet); behavior.addBottomSheetCallback(bottomSheetCallback); behavior.setHideable(cancelable); } return container; }
design_buttom_sheet_dialog.xml
を見ると、design_bottom_sheet
のlayout_height
にwrap_content
が指定されています。*3
<FrameLayout android:id="@+id/design_bottom_sheet" style="?attr/bottomSheetStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|top" app:layout_behavior="@string/bottom_sheet_behavior" />
したがって、design_bottom_sheet
のlayout_height
にmatch_parent
を指定することでレイアウトの表示領域を広げることができます。
次に、2.の「BottomSheetBehavior
のpeekHeight
を画面の縦幅と一致させる」に関連する実装を見ていきます。
BottomSheetDialog#onStart()
ではBottomSheetBehavior
へstateをセットする処理が行われています。
stateのデフォルト値はSTATE_COLLAPSED
となっているので、BottomSheetDialog#onStart()
が呼ばれるまでにstateを明示的にSTATE_HIDDEN
以外へ変更しない限り、縮小された状態でBottomSheetが表示されることになります。
(余談ですが、collapsedという単語の意味をいつも忘れてしまいます…笑)
@Override protected void onStart() { super.onStart(); if (behavior != null && behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) { behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } }
「縮小された状態」とは、具体的には以下の状態です。*4
STATE_COLLAPSED:
The bottom sheet is visible but only showing its peek height.
This state is usually the ‘resting position’ of a Bottom Sheet.
The peek height is chosen by the developer and should be enough to indicate there is extra content, allow the user to trigger an action or expand the bottom sheet.
したがって、BottomSheetBehavior
のpeekHeight
に画面の縦幅を指定することでBottomSheetをフルスクリーン状態で表示できるようになります。
画面の縦幅の取得に関しては以下のサイトが個人的には分かりやすかったです。
以上となります。
個人的にはある程度の整理はできましたが、BottomSheet表示時のロジック(アニメーション含め)が今ひとつ理解できていないので、時間のあるときに改めて見ていきたいと思います。
*1:https://github.com/material-components/material-components-android/blob/4d4f3ccd8f33aa7941988bf8fb2171a61394e509/lib/java/com/google/android/material/bottomsheet/BottomSheetDialogFragment.java#L47-L51
*2:https://github.com/material-components/material-components-android/blob/4d4f3ccd8f33aa7941988bf8fb2171a61394e509/lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java#L269-L282
*3:https://github.com/material-components/material-components-android/blob/4d4f3ccd8f33aa7941988bf8fb2171a61394e509/lib/java/com/google/android/material/bottomsheet/res/layout/design_bottom_sheet_dialog.xml#L41-L47
*4:https://github.com/material-components/material-components-android/blob/181851bffb7985aaeb0934f30baff1edac5c26d0/docs/components/BottomSheet.md#setting-state