Androidマンになりたいおじさん

自分の備忘録的なのです。Androidを普及できたらいいなと思ったりしながら書きます

【Android】BottomSheetDialogFragmentで少しハマったっていう思い出話と解決策

おはよう、こんにちは、おやすみなさい

ぐみおです

BottomSheetDialogFragmentで少しハマったので、自分のために残します

もし同じようなことで悩まれたら、この記事最高〜〜〜〜って思ってもらう数年後のために残すわけではありません

BottomSheetDialogFragment

下からひょこひょこ出てくるアイツのことです 公式みてね material.io

何にハマったのか

f:id:qurangumio:20191202001217g:plain

??????? これでいいじゃんとか思ったでしょ??? ちがう!

画像サイズが固定で指定してるだけでは、だめなんじ〜〜〜〜〜〜〜〜〜^

Constraintの制約によって、ImageViewをユーザの端末ごとによって動的に表示変えたいんです!!!

じゃあ、すればいいじゃんってね 0dp, 0dpにすればいいじゃんってね

f:id:qurangumio:20191202001647g:plain

画像どこいった? この表示のされ方はおかしいぞ????

なぜ

BottomSheetDialogFragmentの親元で使われているBottomSheet表示するためのdesign_bottom_sheetのFrameLayoutのheightがWRAP_CONTENTになっている

<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"/>

github.com

は〜〜〜〜〜〜ほんま!は〜〜〜〜ほんま!

は〜ほんまってなりつつもイマイチいい解決が思いつかなかったのですが、とりあえずこうしてみた

class SampleBottomSheetDialogFragment : BottomSheetDialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return SampleBottomSheetDialog(requireContext())
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = DataBindingUtil.inflate<FragmentSampleBottomSheetDialogBinding>(
            inflater,
            R.layout.fragment_sample_bottom_sheet_dialog,
            container,
            false
        ).apply {
            continueButton.setOnClickListener {
                dismiss()
            }
        }

        return binding.root
    }

    private class SampleBottomSheetDialog(
        context: Context
    ) : BottomSheetDialog(context, 好きなようにstyle作って指定してね) {
        override fun setContentView(view: View) {
            super.setContentView(view)
            val parent = view.parent as? View ?: return

            parent.apply {
                layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
            }

            BottomSheetBehavior.from(parent).run {
                skipCollapsed = true
                state = BottomSheetBehavior.STATE_EXPANDED
            }
        }
    }

    companion object {
        const val TAG = "SampleBottomSheetDialogFragment"
        fun newInstance(): SampleBottomSheetDialogFragment {
            return SampleBottomSheetDialogFragment()
        }
    }
}

Dialogの中にonCreateViewでlayoutがsetされる前に親元のwrap_contentをmatch_parentに書き換えちゃえ作戦ですね.....えいやえいや

override fun onActivityCreated(savedInstanceState: Bundle?)でcontentがdialogにセットされますが、この中でdialogのsetContentViewが呼ばれてるのでBottomSheetDialogを継承したclassのsetContentViewの中に書いちゃいましょう

val parent = view.parent as? View ?: return
parent.apply {
  layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
}

これですね

ほんとにそれでいいんですか!??!?!?は知らないので、もっといい方法あるよって人はこっそり教えて下さい(こっそりですよ)

これを適用したのがこちら

f:id:qurangumio:20191202003307g:plain

よさそう

今回こういう用途として扱いましたが、固定の高さに設定したい場合とかでも使えそうですね

おやすみなさい