NiceToMytyuk
NiceToMytyuk

Reputation: 4317

Unable to set BottomSheetDialog initial height

I'm trying to set a height peek from which the dialog must start, then the user if dragged should be able to expand it, the issue is that in any case the bottomsheet initial state get half of screen.

The BottomSheet looks like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/varianti_preferite_bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:elevation="8dp"
    app:behavior_peekHeight="200dp"
    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

    <ImageButton
        android:id="@+id/closeButton"
        style="@style/Widget.AppCompat.ImageButton"
        android:minWidth="75dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="@drawable/bottom_border_radius"
        android:contentDescription="@string/bottom_sheet_close_button"
        android:padding="10dp"
        android:layout_marginBottom="16dp"
        app:srcCompat="@drawable/ic_baseline_close" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/variantiRecycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="16dp"
        android:clipToPadding="false"
        android:scrollbars="vertical"
        app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
        app:spanCount="4"
        tools:listitem="@layout/varianti_preferite">

    </androidx.recyclerview.widget.RecyclerView>


</LinearLayout>

What i've tried:

I've tried to override onCreateDialog and set HalfExpanded ratio manually but nothing changed:

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

        dialog.setOnShowListener(dialog1 -> {
            BottomSheetDialog d = (BottomSheetDialog) dialog1;

            FrameLayout bottomSheet = (FrameLayout) d.findViewById(com.google.android.material.R.id.design_bottom_sheet);
            BottomSheetBehavior<FrameLayout> bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
            bottomSheetBehavior.setHalfExpandedRatio(0.2f);
            bottomSheetBehavior.setFitToContents(false);

        });

        return dialog;
    }

Kotlin answers are welcome too.

Upvotes: 2

Views: 979

Answers (3)

writer_chris
writer_chris

Reputation: 156

I had struggled with a similar problem, my solution was to set layoutParams

Hope it works for you as well

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewBinding.apply {
        bottomSheetConstraintLayout.layoutParams.height = 
        resources.displayMetrics.heightPixels
    }
}
           

Upvotes: 1

Stepan Kulagin
Stepan Kulagin

Reputation: 515

The way that successfully works for me:

  1. Add viewTreeObserver.addOnGlobalLayoutListener in onCreate to setup your BottomSheet behavior:
binding.root.viewTreeObserver.addOnGlobalLayoutListener {
    setupBottomSheetBehaviorForView(binding.bottomFragmentContainer)
}
  1. Setup behavior:
private fun setupBottomSheetBehaviorForView(view: FragmentContainerView) {
    val behavior = BottomSheetBehavior.from(view)
    val screenHeight =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            windowManager.currentWindowMetrics.bounds.height()
        } else {
            val metrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(metrics)
            metrics.heightPixels
        }

    val toolbarLocation = IntArray(COORDINATES_ARRAY_SIZE) // was added to avoid overlapping the toolbar
    binding.toolbar.getLocationOnScreen(toolbarLocation)   // with the bottom sheet (in case of full screen activity)

    behavior.apply {
        peekHeight = (screenHeight * BOTTOM_SHEET_PEEK_PERCENT).toInt()
        isFitToContents = false
        halfExpandedRatio = BOTTOM_SHEET_PEEK_PERCENT
        expandedOffset = toolbarLocation[1]  // it's optional
    }
}

where BOTTOM_SHEET_PEEK_PERCENT is Float const, for 40% initial peek height:

const val BOTTOM_SHEET_PEEK_PERCENT = 0.40f

Upvotes: 1

NiceToMytyuk
NiceToMytyuk

Reputation: 4317

I've solved the issue by setting peek height in BottomSheet style.

So in style.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">        
   <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="android:background">@drawable/bottom_sheet_rounded</item>
    <item name="behavior_peekHeight">@dimen/peek_height</item>
</style>

Where in dimens.xml

<dimen name="peek_height">200dp</dimen>

But the issue is that it will set the peek_height to all BottomSheets of the application.

Upvotes: 0

Related Questions