Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bottomSheetDialogFragment full screen

What I'm trying to achieve is something like Instagram in-app web browser, used when you click an ad:

Instagram web browser

what I did, is I used a WebView bottomSheetDialogFragment, and I override onCreateDialog to get the full screen like this :

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    BottomSheetDialog bottomSheetDialog=(BottomSheetDialog)super.onCreateDialog(savedInstanceState);
    bottomSheetDialog.setOnShowListener(dialog -> {
        BottomSheetDialog dialogc = (BottomSheetDialog) dialog;
        FrameLayout bottomSheet =  dialogc .findViewById(android.support.design.R.id.design_bottom_sheet);
        BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_EXPANDED);
        //BottomSheetBehavior.from(bottomSheet).setSkipCollapsed(true);
        //BottomSheetBehavior.from(bottomSheet).setHideable(true);
    });
    return bottomSheetDialog;
}

here is the result I get :

web browser

my question is, how can I get the full screen effect, or how can achieve something like instagram browser?

ps: I tried first chrome custom tabs, but I couldn't add it inside dialog fragment.

Thank you.

like image 822
Abdel Avatar asked Sep 23 '19 15:09

Abdel


People also ask

How do I make Bottomsheetdialogfragment full screen?

add a view with "android:layout_height="match_parent" into root layout. when dialog is shown (or before this) update of BottomSheetBehavior with "isFitToContents = false" and "state = BottomSheetBehavior. STATE_EXPANDED".

What is bottom sheet in Android?

Bottom Sheet dialogs seem to be replacing regular Android dialogs and menus. The Bottom Sheet is a component that slides up from the bottom of the screen to showcase additional content in your application. A Bottom Sheet dialog is like a message box triggered by the user's actions.


10 Answers

In your custom BottomSheetDialogFragment you can use something like:

  @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) {     Dialog dialog = super.onCreateDialog(savedInstanceState);     dialog.setOnShowListener(new DialogInterface.OnShowListener() {       @Override public void onShow(DialogInterface dialogInterface) {         BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;         setupFullHeight(bottomSheetDialog);       }     });     return  dialog;   }     private void setupFullHeight(BottomSheetDialog bottomSheetDialog) {     FrameLayout bottomSheet = (FrameLayout) bottomSheetDialog.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);   }    private int getWindowHeight() {     // Calculate window height for fullscreen use     DisplayMetrics displayMetrics = new DisplayMetrics();     ((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);     return displayMetrics.heightPixels;   } 
like image 141
Gabriele Mariotti Avatar answered Sep 28 '22 10:09

Gabriele Mariotti


Sorry for the late answer but in your custom BottomSheetDialogFragment you can set match_parent to layout params of bottom sheet view like this:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = BottomSheetDialog(requireContext(), theme)
    dialog.setOnShowListener {

        val bottomSheetDialog = it as BottomSheetDialog
        val parentLayout =
            bottomSheetDialog.findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
        parentLayout?.let { it ->
            val behaviour = BottomSheetBehavior.from(it)
            setupFullHeight(it)
            behaviour.state = BottomSheetBehavior.STATE_EXPANDED
        }
    }
    return dialog
}

private fun setupFullHeight(bottomSheet: View) {
    val layoutParams = bottomSheet.layoutParams
    layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
    bottomSheet.layoutParams = layoutParams
}

Setting height to match_parent helps your dialog to be drawn above the inset of Navigation bar

like image 20
lukaspp Avatar answered Sep 28 '22 10:09

lukaspp


You can do it by setting peekHeight of BottomSheetBehavior to be equal to Resources.getSystem().getDisplayMetrics().heightPixels:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    BottomSheetDialog bottomSheetDialog=(BottomSheetDialog)super.onCreateDialog(savedInstanceState);
    bottomSheetDialog.setOnShowListener(dialog -> {
        BottomSheetDialog dialogc = (BottomSheetDialog) dialog;
        // When using AndroidX the resource can be found at com.google.android.material.R.id.design_bottom_sheet
        FrameLayout bottomSheet =  dialogc.findViewById(android.support.design.R.id.design_bottom_sheet);

        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
        bottomSheetBehavior.setPeekHeight(Resources.getSystem().getDisplayMetrics().heightPixels);
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    });
    return bottomSheetDialog;
}
like image 22
Natig Babayev Avatar answered Sep 28 '22 10:09

Natig Babayev


Proposed solutions are based on using an internal id, since it is not on purpose exposed it could change without warning.

My solution set the layout height to the FrameLayout but in a more abstract way, so if it changes it shouldn't break, even if the ViewGroup type change.

override fun onStart() {
    super.onStart()
    val sheetContainer = requireView().parent as? ViewGroup ?: return
    sheetContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
}

If you take a look at the BottomSheetDialog the private View wrapInBottomSheet method you will see this happens to guarantee the sheet behavior. Some extra debugging, allowed me to figure the fragment View is the direct child from the FrameLayout everybody is finding by id.

In this way, you don't need to rely on the ID. I'm using onStart because is defined at the point when the fragment is ready for interactions, so all should be ready.

And if you need it full height from the start (most probably)

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return BottomSheetDialog(requireContext(), theme).apply {
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
        behavior.peekHeight = //your harcoded or dimen height
    }
}
like image 20
cutiko Avatar answered Sep 28 '22 11:09

cutiko


Here's how you do it in kotlin,

val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener {
    val bottomSheetDialog = it as BottomSheetDialog
    val parentLayout = bottomSheetDialog.findViewById<View>(
        com.google.android.material.R.id.design_bottom_sheet
    )
    parentLayout?.let { bottomSheet ->
        val behaviour = BottomSheetBehavior.from(bottomSheet)
        val layoutParams = bottomSheet.layoutParams
        layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT
        bottomSheet.layoutParams = layoutParams
        behaviour.state = BottomSheetBehavior.STATE_EXPANDED
    }
}
return dialog
like image 20
Kasun Thilina Avatar answered Sep 28 '22 10:09

Kasun Thilina


The best way to to this is through XML

Customize default BottomSheet by overriding it's attributes, for example in styles.xml

<style name="Widget.MyApp.BottomSheet.Modal" parent="Widget.MaterialComponents.BottomSheet.Modal">
    <item name="behavior_skipCollapsed">true</item>
    <item name="behavior_fitToContents">true</item>
    <item name="behavior_peekHeight">1000dp</item> // yep, that helped to skip collapsed state at initial
    <item name="behavior_hideable">true</item>
</style>

Go inside Widget.MaterialComponents.BottomSheet.Modal to see what settings you can modify.

Then create custom theme inherited from Theme.Design.BottomSheetDialog and set that you want to override bottom sheet's style with you own. Also can be placed in styles.xml

<style name="Theme.MyApp.BottomSheetDialog" parent="Theme.Design.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/Widget.MyApp.BottomSheet.Modal</item>
</style>

And the last, define your new created theme for bottom sheet dialog in your Activity's theme or Application's theme, which placed in themes.xml(hope you follow Google's recommendations about packaging styles&themes)

<style name="Base.Theme.MyApp" parent="Base.Theme.Root">
    ... too many other things
    <item name="bottomSheetDialogTheme">@style/Theme.MyApp.BottomSheetDialog</item>
like image 23
Stack Fox Avatar answered Sep 28 '22 10:09

Stack Fox


You can do it by changing the state of your dialog to STATE_EXPANDED:

BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
dialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);

Kotlin:

val dialog = dialog as BottomSheetDialog
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
like image 42
AliSh Avatar answered Sep 28 '22 10:09

AliSh


I used such way:

  • add a view with "android:layout_height="match_parent" into root layout
  • when dialog is shown (or before this) update of BottomSheetBehavior with "isFitToContents = false" and "state = BottomSheetBehavior.STATE_EXPANDED".

Code:

override fun onShow(dialog: DialogInterface?) {
    BottomSheetBehavior.from(binding?.root?.parent as View).apply {
        isFitToContents = false
        state = BottomSheetBehavior.STATE_EXPANDED
    }
}

Xml file:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/fragment_cities_root_background">

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <!-- other views -->

    </androidx.constraintlayout.widget.ConstraintLayout >
like image 36
Max M Avatar answered Sep 28 '22 09:09

Max M


just add below line of code

bottomSheetDialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);

and layout should be inside NestedScrollView

like image 27
manu mathew Avatar answered Sep 28 '22 11:09

manu mathew


try this in your custom BottomSheetDialogFragment:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupFullHeight()

    }

    private fun setupFullHeight() {
        val bottomSheetDialog = dialog as BottomSheetDialog
        val behavior = bottomSheetDialog.behavior
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }
like image 32
hamid keyhani Avatar answered Sep 28 '22 11:09

hamid keyhani