Android BottomSheetDialogFragment not expandable

I have the following test bottom sheet implementation.

When I set peehHight to a value less than 500, it works. After a certain value, any increase in clearance height will not change the way the bottom sheet expands. He just stays there only by hand. How we install peekHeight programmatically to ensure that the bottom sheet is automatically expanded to the peeking height.

enter image description here

bottom_sheet_dialog_main

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/locUXCoordinatorLayout" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/locUXView" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:orientation="vertical" app:behavior_hideable="false" app:behavior_peekHeight="0dp" app:layout_behavior="@string/bottom_sheet_behavior"> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="1 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="2 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="3 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="4 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="5 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="6 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="7 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="8 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="9 Value" /> <TextView android:layout_width="match_parent" android:layout_height="100dp" android:text="First Value" /> </LinearLayout> </android.support.design.widget.CoordinatorLayout> 

Java code

 public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment { private static BottomSheetBehavior bottomSheetBehavior; private static View bottomSheetInternal; private static MyBottomSheetDialogFragment INSTANCE; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { getDialog().setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; CoordinatorLayout coordinatorLayout = (CoordinatorLayout)d.findViewById(R.id.locUXCoordinatorLayout); bottomSheetInternal = d.findViewById(R.id.locUXView); bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal); bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight()); bottomSheetInternal.requestLayout(); coordinatorLayout.getLayoutParams().height = bottomSheetInternal.getHeight(); Toast.makeText(getActivity(), "Height is" + bottomSheetInternal.getHeight() + " " + coordinatorLayout.getLayoutParams().height, Toast.LENGTH_LONG).show(); } }); INSTANCE = this; return inflater.inflate(R.layout.bottom_sheet_dialog_main, container, false); } } 
+19
java android android-support-library android-support-design bottom-sheet
source share
6 answers

A deeper check of the user interface, we find that there is another CoordinatorLayout that our coordinator wraps. Parent CoordinatorLayout has FrameLayout with BottomSheetBehavior with id design_bottom_sheet . The peeking height set in our code above was limited due to the match_parent FrameLayout height match_parent FrameLayout identifier

By setting the peek FrameLayout height with the design_bottom_sheet id, this problem was resolved.

  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { getDialog().setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; coordinatorLayout = (CoordinatorLayout) d.findViewById(R.id.locUXCoordinatorLayout); bottomSheetInternal = d.findViewById(R.id.locUXView); bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal); bottomSheetBehavior.setHidable(false); BottomSheetBehavior.from((View)coordinatorLayout.getParent()).setPeekHeight(bottomSheetInternal.getHeight()); bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight()); coordinatorLayout.getParent().requestLayout(); } }); 
+9
source share

Using this code in onCreateView.

 getDialog().setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { BottomSheetDialog d = (BottomSheetDialog) dialog; FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.design_bottom_sheet); CoordinatorLayout coordinatorLayout = (CoordinatorLayout) bottomSheet.getParent(); BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet); bottomSheetBehavior.setPeekHeight(bottomSheet.getHeight()); coordinatorLayout.getParent().requestLayout(); } }); 
+23
source share

I found another solution. Perhaps for future readers this may be useful.

 @Override public void setupDialog(Dialog dialog, int style) { super.setupDialog(dialog, style); final View root = View.inflate(getContext(), R.layout.fragment_bottom_sheet_choose_time, null); dialog.setContentView(root); initView(root); CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) root.getParent()).getLayoutParams(); CoordinatorLayout.Behavior behavior = params.getBehavior(); if (behavior != null && behavior instanceof BottomSheetBehavior) { mBottomSheetBehavior = (BottomSheetBehavior) behavior; mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback); root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { root.getViewTreeObserver().removeGlobalOnLayoutListener(this); int height = root.getMeasuredHeight(); mBottomSheetBehavior.setPeekHeight(height); } }); } } 

As @Anthonyeef mentioned, here ViewTreeObserver aims to get the exact height of the measurement after the view is actually measured and the GlobalOnLayoutListener removed for better performance.

But please, before using it in production, test this solution on different devices and screens, because if your content in the bottom sheet is higher than your screen, it can cause some strange behavior when passing.

+18
source share

Thanks @athysirus for the neat approach. Here is the version I settled on, in case someone wants to get a working kotlin sample.

It is important to note that you should also remove the global layout listener as soon as this is done.

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { val bottomSheet = (dialog as BottomSheetDialog).findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) BottomSheetBehavior.from<View>(bottomSheet).apply { state = BottomSheetBehavior.STATE_EXPANDED peekHeight = 0 } view.viewTreeObserver.removeOnGlobalLayoutListener(this) } }) 
+1
source share

Kotlin solution inspired by Nandish A post in more detail. First layout:

 <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/container_root" android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" app:behavior_hideable="false" app:behavior_peekHeight="0dp" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> <!-- content of the bottom sheet --> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout> 

And then paste this into your BottomSheetDialogFragment :

 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // ... dialog.setOnShowListener { val root = dialog.find<CoordinatorLayout>(R.id.container_root) val bottomSheetInternal = root.find<ConstraintLayout>(R.id.bottom_sheet) val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal) bottomSheetBehavior.isHideable = false BottomSheetBehavior.from(root.parent as View).peekHeight = root.height bottomSheetBehavior.peekHeight = root.height root.parent.requestLayout() } // ... } 
0
source share

this is how i set peek_height and layout_height to the bottom view of the sheet

 dialog?.setOnShowListener { val dialog = dialog as BottomSheetDialog val bottomSheet = dialog.findViewById<FrameLayout>(R.id.design_bottom_sheet) val coordinatorLayout = bottomSheet?.parent as? CoordinatorLayout val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet) bottomSheet?.viewTreeObserver?.addOnGlobalLayoutListener { bottomSheet.viewTreeObserver.removeOnGlobalLayoutListener {} bottomSheetBehavior.peekHeight = getPopupHeight(.5f) val params = bottomSheet.layoutParams params.height = getPopupHeight(1f) bottomSheet.layoutParams = params coordinatorLayout?.parent?.requestLayout() } } 

this method to get a percentage of the height of the screen

  private fun getPopupHeight(percent: Float): Int { val displayMetrics = DisplayMetrics() activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics) return (displayMetrics.heightPixels * percent).toInt() } 
0
source share

All Articles