Set state of BottomSheetDialogFragment to expanded

Viewed 122450

How do you set the state of a fragment extending BottomSheetDialogFragment to expanded using BottomSheetBehavior#setState(STATE_EXPANDED) using the Android Support Design Library (v23.2.1)?

https://code.google.com/p/android/issues/detail?id=202396 says:

Bottom sheets are set to STATE_COLLAPSED at first. Call BottomSheetBehavior#setState(STATE_EXPANDED) if you want to expand it. Note that you cannot call the method before view layouts.

The suggested practice requires a view to be inflated first, but I'm not sure how I'll set the BottomSheetBehaviour onto a fragment (BottomSheetDialogFragment).

View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);  
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);  
20 Answers

A simplistic and elegant solution:

BottomSheetDialogFragment could be subclassed to address this:

class NonCollapsableBottomSheetDialogFragment extends BottomSheetDialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);

        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);

                BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
                behavior.setSkipCollapsed(true);
                behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });
        return dialog;
    }
}

So extend this class instead of BottomSheetDialogFragment to create your own bottom sheet.

Note

Change com.google.android.material.R.id.design_bottom_sheet to android.support.design.R.id.design_bottom_sheet if your project uses old Android support libraries.

I think those above is better. Sadly I did not find those solution before I had solved. But write my solution. quite similar to all.

==================================================================================

I face the same issue. This is what I solved. The Behavior is hidden in BottomSheetDialog, which is available to get the behavior If you would like not to change your parent layout to be CooridateLayout, you can try this.

STEP 1: customize the BottomSheetDialogFragment

open class CBottomSheetDialogFragment : BottomSheetDialogFragment() {
   //wanna get the bottomSheetDialog
   protected lateinit var dialog : BottomSheetDialog 
   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
      dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
      return dialog
   }

   //set the behavior here
   fun setFullScreen(){
      dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
   }
}

STEP 2: make your fragment extend this customized fragment

class YourBottomSheetFragment : CBottomSheetDialogFragment(){
    
   //make sure invoke this method after view is built
   //such as after OnActivityCreated(savedInstanceState: Bundle?)
   override fun onStart() {
      super.onStart()
      setFullScreen()//initiated at onActivityCreated(), onStart()
   }
}

BottomSheetDialogFragment:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (dialog as? BottomSheetDialog)?.behavior?.state = STATE_EXPANDED
}

or when ready to show:

private fun onContentLoaded(items: List<Any>) {
    adapter.submitList(items)
    (dialog as? BottomSheetDialog)?.behavior?.state = STATE_EXPANDED
}

In Kotlin, add the below line in onStart() of your BottomSheetDialogFragment

(dialog as BottomSheetDialog).behavior.state = BottomSheetBehavior.STATE_EXPANDED

My answer is more or less same as most of the above answers with a slight modification. Instead of using findViewById to first find the bottom sheet view, I have preferred not to hardcode any framework view resource ids since they might change in future.

setOnShowListener(dialog -> {
            BottomSheetBehavior bottomSheetBehavior = ((BottomSheetDialog)dialog).getBehavior();
            bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        });
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState).apply {
        setOnShowListener {
            (this@TipsBottomDialogFragment.dialog as BottomSheetDialog).behavior.setState(
                BottomSheetBehavior.STATE_EXPANDED
            )
        }
    }
}

Posting this here to future readers, as I think now we can use another solution.

I was trying to solve the same problem you described with a BottomSheetDialog.

I don't like using internal Android ids and I've just found there's a method inside BottomSheetDialog getBehavior that you can use:

You can use this inside your BottomSheetDialog:

behavior.state = BottomSheetBehavior.STATE_EXPANDED

Using BottomSheetDialogFragment you can do the same casting the dialog from that DialogFragment to BottomSheetDialog.

In your Kotlin BottomSheetDialogFragment class, override onCreateDialog as below

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val bottomSheetDialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
        bottomSheetDialog.setOnShowListener {
            val bottomSheet =
                bottomSheetDialog.findViewById<FrameLayout>(
                    com.google.android.material.R.id.design_bottom_sheet
                )
            val behavior = BottomSheetBehavior.from(bottomSheet!!)
            behavior.skipCollapsed = true
            behavior.state = BottomSheetBehavior.STATE_EXPANDED
        }
        return bottomSheetDialog
    }

You can do the following (Kotlin version):

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    dialog?.let {
        val sheet = it as BottomSheetDialog
        sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

    // rest of your stuff
}

Apply BottomsheetDialogFragment state in onResume will solve this issue

@Override
public void onResume() {
    super.onResume();
    if(mBehavior!=null)
       mBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}

onShow(DialogInterface dialog) and postDelayed may cause animation glitch

Similar to uregentx answer, in kotlin, you can declare your fragment class that extends from BottomSheetDialogFragment, and when the view is created you can set the dialog listener default state after the dialog is displayed.

STATE_COLLAPSED: The bottom sheet is visible but only showing its peek height.

STATE_EXPANDED: The bottom sheet is visible and its maximum height.

STATE_HALF_EXPANDED: The bottom sheet is visible but only showing its half height.

class FragmentCreateGroup : BottomSheetDialogFragment() {
      ...

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
        // Set dialog initial state when shown
        dialog?.setOnShowListener {
            val bottomSheetDialog = it as BottomSheetDialog
            val sheetInternal: View = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet)!!
            BottomSheetBehavior.from(sheetInternal).state = BottomSheetBehavior.STATE_COLLAPSED
        }

        val view = inflater.inflate(R.layout.fragment_create_group, container, false)
        ...

        return view
    }
}

Remember using material design implementation in gradle.

implementation "com.google.android.material:material:$version"

Also take a look to material design reference Bottom Sheets

The easiest way I implemented is as below, Here we are finding android.support.design.R.id.design_bottom_sheet and setting bottom sheet state as EXPANDED.

Without this, my bottom sheet was always stuck in the COLLAPSED state if view height is more than 0.5 of screen height and I have to manually scroll to view full bottom sheet.

class BottomSheetDialogExpanded(context: Context) : BottomSheetDialog(context) {

    private lateinit var mBehavior: BottomSheetBehavior<FrameLayout>

    override fun setContentView(view: View) {
        super.setContentView(view)
        val bottomSheet = window.decorView.findViewById<View>(android.support.design.R.id.design_bottom_sheet) as FrameLayout
        mBehavior = BottomSheetBehavior.from(bottomSheet)
        mBehavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

    override fun onStart() {
        super.onStart()
        mBehavior.state = BottomSheetBehavior.STATE_EXPANDED
    }
}

Here is a pretty neat Kotlin solution that works great.

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return (super.onCreateDialog(savedInstanceState) as BottomSheetDialog).apply {
        setOnShowListener {
           behavior.state = BottomSheetBehavior.STATE_EXPANDED
        }
    }
}

Simple Solution to expand the BottomSheet view in Kotlin:

(dialog as BottomSheetDialog).behavior.state = 
    BottomSheetBehavior.STATE_EXPANDED

Simple answer (Kotlin + fragment + bottomSheetDialogViewBinding) :

val bsd = BottomSheetDialog(requireContext())
val bsdBinding = DialogBottomSheetViewBinding.inflate(LayoutInflater.from(requireContext()))
bsd.behavior.setState(BottomSheetBehavior.STATE_EXPANDED);

That's what worked for me, based on the response from the link below.

behavior = BottomSheetBehavior.from(bottomSheet1);
if(action.equals("post") ) {
    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    behavior.setDraggable(false); // disable dragging
}

enter link description here

Related