BottomSheetBehavior の state と OnBackPressedDispatcher を連携する
Sep 14, 2021 00:41 · 567 words · 2 minute read
どうもこんにちは、geckour です。
今回は、タイトルの通り BottomSheetBehavior の state によって OnBackPressedDispatcher の制御をしようとして若干手間取ったのでまとめておきます。
実装
やりたいことは BottomSheetBehavior#state
が BottomSheetBehavior.STATE_EXPANDED
の場合のみバックキーの制御を奪い、ボトムシートを閉じるというものです。
が、実装を見てもらえればそれが全てだと思うので以下に示します。
class HogeFragment() : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
val behavior = BottomSheetBehavior<View>.from(
// The view that has been added an attribute of app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
(requireActivity() as HogeActivity).binding.bottomSheet
)
val bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(v: View, dy: Float) {
binding.sheet.progress = dy
}
override fun onStateChanged(v: View, state: Int) {
onBackPressedCallback.isEnabled = state == BottomSheetBehavior.STATE_EXPANDED
}
}
behavior.addBottomSheetCallback(bottomSheetCallback)
onBackPressedCallback =
object : OnBackPressedCallback(behavior.state == BottomSheetBehavior.STATE_EXPANDED) {
override fun handleOnBackPressed() {
viewModel.toggleSheetState.value = Unit
}
}
requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
}
}
(一応) 解説
軽く解説もしておきます。
まず、 OnBackPressedDispatcher
では Activity#onBackPressed()
のように super.onBackPressed()
を呼んでデフォルトのバックキーの制御を行うということができません。
そこで、OnBackPressedDispatcher#isEnabled
の値を変化させることによってコールバックの実行を制御できる仕組みを利用します。
具体的には、 OnBackPressedDispatcher
を以下のようにラムダ式を使って宣言するのではなく、インスタンスとして保持します。
その上で、OnBackPressedDispatcher#isEnabled
は外部から set
できるので、BottomSheetBehavior.BottomSheetCallback
を利用して state
を見て値を制御してあげます。
OnBackPressedDispatcher#isEnabled
は外部から set
できる、ここが一番大事で、それさえ押さえておけば色々応用が効くと思います。