ianhanniballake
ianhanniballake

Reputation: 199825

How do I change the default height of a BottomSheetDialog?

I've been using the new BottomSheetDialog added in Support Library 23.2, but I want to change the default height of the dialog. I know it probably has to do with the behavior_peekHeight attribute which controls the initial height, but how do I set that in the BottomSheetDialog when I don't have direct access to the BottomSheetBehavior?

Upvotes: 56

Views: 79565

Answers (18)

Vikram Vishwakarma
Vikram Vishwakarma

Reputation: 11

BottomSheetDialog dialog = new BottomSheetDialog(this);
.
.
.
dialog.getBehavior().setPeekHeight(100);

This way you can set the bottom sheet dialog peek height without doing anything else.

Upvotes: 0

Fang
Fang

Reputation: 3665

styles.xml

<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>

<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
    <item name="behavior_peekHeight">500dp</item>
</style>
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.BottomSheetDialog);
dialog.setContentView(R.layout.layout_bottom_sheet);
dialog.show();

Upvotes: 19

ked
ked

Reputation: 2456

My bottom sheet dialog had recycler view and didn't had items to show, so it was shrinking, but let's say u want to set peek height to 85% irrespective of items present in Recyclerview or not, try this solution.

Add the following code in class which extends BottomSheetDialogFragment

override fun onStart() {
    super.onStart()
    (dialog as BottomSheetDialog).behavior.peekHeight = getBottomSheetDialogDefaultHeight()
    dialog?.let {
        val bottomSheet = it.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
    }
}

private fun getBottomSheetDialogDefaultHeight(): Int {
    val displayMetrics = DisplayMetrics()
    (context as Activity?)?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
    return displayMetrics.heightPixels * 85 / 100
}

Upvotes: 6

Le Trung Hieu
Le Trung Hieu

Reputation: 174

Use this code to set height of DialogFragment or BottomSheetDialogFragment. The dialog will adjust its height with different screen height

  override fun onStart() {
        super.onStart()
        val window = dialog?.window
        val ratio = 1.0

        if (window != null && activity != null) {
            val heightDialog = (getScreenHeight(requireActivity()) * 0.9f).toInt()
            window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, (heightDialog * ratio).toInt())
            window.setGravity(Gravity.BOTTOM)
        }
    }

Upvotes: 0

RoK
RoK

Reputation: 1097

If you are extending BottomSheetDialogFragment, you can do the following to get hold of BottomSheetBehavior:

public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    Dialog dialog = super.onCreateDialog(savedInstanceState);
    //Must add any view here, actual view will be inflated in onCreateView
    dialog.setContentView(new View(getContext()));
    //Dialog wraps view in frame layout
    View root = dialog.findViewById(R.id.design_bottom_sheet);
    //Now we have access to BottomSheetBehavior
    BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(root);
    //Do whatever you need:
    behavior.setPeekHeight(320, true);
    behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);

    return dialog;
}

Then override onCreateView as usual:

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    //inflate your bottom sheet layout:
    View root = inflater.inflate(R.layout.browser_bottom_sheet, container, false);
    //Do what you need with views:
    ViewPager viewPager = root.findViewById(R.id.viewpager);
                  ...........

    return root;
}

Upvotes: 1

iamkdblue
iamkdblue

Reputation: 3632

This is working for me to show BottomSheetDialog full screen(STATE_EXPANDED).I am using this in my Activity.

private void showBottomSheetDialog() {
        View dialogView = LayoutInflater.from(this).inflate(R.layout.your_custom_layout, null);
        BottomSheetDialog dialog = new BottomSheetDialog(NewWorkoutPlanActivity.this);
        dialog.setContentView(dialogView);

       
        FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(R.id.design_bottom_sheet);
        BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
        ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();

        int windowHeight = getWindowHeight();
        if (layoutParams != null) {
            layoutParams.height = windowHeight;
        }
        bottomSheet.setLayoutParams(layoutParams);
        behavior.setState(BottomSheetBehavior.STATE_EXPANDED);

        dialog.show();

    }

    private int getWindowHeight() {
        // Calculate window height for fullscreen use
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.heightPixels;
    }

Upvotes: 1

ivan8m8
ivan8m8

Reputation: 447

Honestly, I've got no idea why nobody has mentioned these simple ways, yet:

override fun onResume() {
    super.onResume()

    dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
    // or since com.google.android.material:material:1.1.0-beta01
    (dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED

}
//or
dialog.behavior.peekheight = YOUR_VALUE

Directly answering the question

Q: How can I directly access the BottomSheetBehavior height?

A: dialog.behavior.peekheight

Upvotes: 11

LCZ
LCZ

Reputation: 729

You can retrieve the BottomSheetBehavior object from getBehaviour() in the onStart() method, then modify the peek height from there.

@Override
protected void onStart() {
    super.onStart();
    getBehavior().setPeekHeight(/* Peek Height in px */);
}

Upvotes: 0

Divyanshu Kumar
Divyanshu Kumar

Reputation: 1461

If you are using BottomSheetDialogFragment, copy and paste this code

private View bottomSheet;

@Override public void onStart() {
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null) {
      bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
      }
      View view = getView();
      view.post(() -> {
        View parent = (View) view.getParent();
        CoordinatorLayout.LayoutParams params =
            (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
        CoordinatorLayout.Behavior behavior = params.getBehavior();
        BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
      bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
// Here you can play with the height of the bottom sheet like pass height as- [view.getMeasuredHeight()/2]

            ((View) bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
          });
        }
      }

Upvotes: 2

Mostafa Monowar
Mostafa Monowar

Reputation: 921

You can use BottomSheetDialogFragment and do it programatically also.

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    (dialog as? BottomSheetDialog)?.let {
      it.behavior.peekHeight = PEEK_HEIGHT
    }
    return inflater.inflate(R.layout.bottom_sheet_dialog_fragement, container, false)
  }

Upvotes: 3

boileryao
boileryao

Reputation: 21

The really approach we want to achieve this is actual make the LayoutParams works. When inflating content view of the dialog, not passing the parentView in the dialog Window will make xml config of the rootView does NOT actually work.

So here is a solution:

val contentWidth = ViewGroup.LayoutParams.MATCH_PARENT
val contentHeight = 500 // px
dialog.setContentView(view, ViewGroup.LayoutParams(contentWidth, contentHeight))

Upvotes: 0

HelloCsl
HelloCsl

Reputation: 221

Woks for me

  override fun onStart() {
    super.onStart()
    dialog?.also {
        val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
        bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
        val behavior = BottomSheetBehavior.from<View>(bottomSheet)
        behavior.peekHeight = resources.displayMetrics.heightPixels //replace to whatever you want
        view?.requestLayout()
    }
}

Upvotes: 15

Vitaliy Belyaev
Vitaliy Belyaev

Reputation: 11

This is how I decided on the problem:

   override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = BottomSheetDialog(context)
        val view = View.inflate(context, R.layout.bottom_dialog, null)

        val heightInPixels = 500
        val params = ViewGroup.LayoutParams(MATCH_PARENT, heightInPixels)

        dialog.setContentView(view, params)

        return dialog
    }

The main part is method setContentView(view, params), where you set view for your dialog and layout parameters in which you set the desired height.

Upvotes: 1

Pratik Butani
Pratik Butani

Reputation: 62421

I got one hack and used it.

If you want to do programmatically.

    behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View view, int i) {
            behavior.setPeekHeight(yourMinHeight);
        }

        @Override
        public void onSlide(@NonNull View view, float v) {

        }
    });

Thank you.

Upvotes: 0

ianhanniballake
ianhanniballake

Reputation: 199825

You can set a bottomSheetDialogTheme in your Activity, overriding the bottomSheetStyle attribute's behavior_peekHeight:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
</style>

<style name="AppBottomSheetDialogTheme"
       parent="Theme.Design.Light.BottomSheetDialog">
  <item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>

<style name="AppModalStyle"
       parent="Widget.Design.BottomSheet.Modal">
  <item name="behavior_peekHeight">@dimen/custom_peek_height</item>
</style>

This same technique can be used for other attributes as well, such as adding <item name="behavior_hideable">true</item> to the AppModalStyle to change whether the bottom sheet is hideable.

Upvotes: 85

Yuchen
Yuchen

Reputation: 33036

Combining Nick and litao's solution, this is a complete version of what we do:

 BottomSheetDialog bottomSheet = new BottomSheetDialog(context);
 View view = View.inflate(context, R.layout.your_action_sheet, null);
 bottomSheet.setContentView(view);
 BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(((View) view.getParent()));
 bottomSheetBehavior.setPeekHeight(1000);
 bottomSheet.show();

Upvotes: 1

litao
litao

Reputation: 239

you can use BottomSheetBehaviorin your code

BottomSheetDialog dialog = new BottomSheetDialog(content);
.
.
.
dialog.setContentView(view);
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
mBehavior.setPeekHeight(your dialog height)
dialog.show();

Upvotes: 27

Nikola Despotoski
Nikola Despotoski

Reputation: 50538

Another way is inheriting BottomSheetDialogFragment and have control how and when you set the content view. Going up the view tree, you can get the behavior that BottomSheetDialog wraps up the content view. It's not really good solution, because it requires more layout passes. It is important that when the state of the bottom sheet is STATE_HIDDEN we have to dismiss the dialog, if we don't we clearly violate the implementation provided in the library.

After setting the peek height programmatically, content view must call requestLayout() which is indeed another layout pass.

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {


    private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {

        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            setStateText(newState);
            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                dismiss();
            }

        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
        }
    };

@Override
    public void setupDialog(Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        View contentView = View.inflate(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
        dialog.setContentView(contentView);
        mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
        if (mBottomSheetBehavior != null) {
           mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);    
           mBottomSheetBehavior.setPeekHeight(peekHeight);
           contentView.requestLayout();
        }
}

Upvotes: 5

Related Questions