0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AndroidAdvent Calendar 2023

Day 24

[Android] BottomSheetDialog にフッターを設定する

Posted at

この記事は Android Advent Calendar 2023 24日目の記事…です。

フッターを設定する

レイアウトファイルでいい感じに設定する…のはできないので、フッターの位置を計算して表示する必要があります。

addBottomSheetCallbackでスライドしたことをハンドリングすることができます。

FirstBottomSheetDialogFragment.kt
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val bottomSheetDialog = BottomSheetDialog(requireContext())
    val fullScreenHeight = getFullScreenHeight()

    bottomSheetDialog.setOnShowListener { dialog ->
        (dialog as? BottomSheetDialog)?.findViewById<FrameLayout>(R.id.design_bottom_sheet)
            ?.let {
                BottomSheetBehavior.from(it).apply {
                    // ・・・
                    addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
                        override fun onStateChanged(bottomSheet: View, newState: Int) {}

                        override fun onSlide(bottomSheet: View, slideOffset: Float) {
                            // ここでスライドしたことをハンドリングできる
                        }
                    })
                }
            }
    }

    return bottomSheetDialog
}

スライドされた時に表示位置を計算してフッターに設定したいViewのy座標に設定します。

onCreateDialog
// ・・・
addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
    override fun onStateChanged(bottomSheet: View, newState: Int) {}

    override fun onSlide(bottomSheet: View, slideOffset: Float) {
        val currentBottomSheetHeight = fullScreenHeight - bottomSheet.top
        val currentFooterHeight =
            currentBottomSheetHeight - binding.footerView.height

        binding.footerView.y = currentFooterHeight.toFloat()
    }
}.apply {
    binding.root.post { onSlide(binding.root.parent as View, 0f) }
})
// ・・・

結果

フッターを設定したときのgif

Edge to edgeとの干渉

BottomSheetDialog は edge-to-edge の影響を受けます。
公式のサイトより、R.attr.navigationBarColor が transparent または translucent で、enableEdgeToEdgeがtrueの時は自動的にEdge to edgeのwindow flagsが自動的に適用されます。これによって、BottomSheetDialogFragmentが全画面を覆う時、status bar以上の高さになると自動的にパディングが追加されます。

この追加されたパディングによって、フッターの計算がズレます。そのため、フッターを設定するのであればEdge to edgeにならないように設定を変更するか、BottomSheetDialogFragmentが全画面を覆わないようにmaxHeightをstatus barの高さを引いた画面の高さに設定する必要があります。

// ・・・
BottomSheetBehavior.from(it).apply {
    maxHeight = getFullScreenHeight() - getStatusBarHeight()
}
// ・・・
動画
こんな感じでstatus bar以上の高さになるとフッターがズレてしまう フッターがズレるgif

maxHeightをstatus barを引いた高さに設定するとこんな感じ
maxHeightを設定したgif

ちなみに公式でもフッターを設定しているような BottomSheetDialog がありますが、内部にスクロールを入れて BottomSheetDialog自体がスクロールしないようになっていました。 その方が良いです。

参考

Static Footer View On Android Bottom Sheet - Stack OverFlow
BottomSheetBehavior - Android Developers

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?