34

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.

Gabriele Mariotti
  • 192,671
  • 57
  • 469
  • 489
Abdel
  • 697
  • 2
  • 7
  • 22
  • Right solution: https://stackoverflow.com/questions/33644326/hiding-status-bar-while-showing-alert-dialog-android#answer-40744282 – ATES May 20 '21 at 22:15

5 Answers5

66

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;
  }
Gabriele Mariotti
  • 192,671
  • 57
  • 469
  • 489
  • 1
    Isn't working for me. Only gets me around 70% up the screen. Any suggestions? – Code Wiget Mar 26 '20 at 20:43
  • @CodeWiget might be because the content of your bottom sheet isnt large enough to stretch through the whole screen – AsafK May 07 '20 at 14:04
  • If you need the full height without statusbar you should call: (context as Activity).findViewById(Window.ID_ANDROID_CONTENT).height – G00fY May 13 '20 at 14:08
  • it's kinda a fixed size for its content view. – Ken Zira May 23 '20 at 16:57
  • 6
    Those who cannot access `android.support.design.R.id.design_bottom_sheet` can try the following: `com.google.android.material.R.id.design_bottom_sheet` – Egemen Hamutçu Jul 07 '20 at 10:07
  • @AsafK what can I do to achieve the same if my content isn't large enough to stretch all the available screen? It's a list and it might be empty – Krusty Jan 25 '21 at 23:01
  • hey can you help here https://stackoverflow.com/questions/66533461/issue-in-creating-a-transparent-activity-on-top-of-another-activity – apj123 Mar 09 '21 at 06:29
25

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

lukaspp
  • 589
  • 6
  • 12
20

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;
}
Natig Babayev
  • 2,290
  • 9
  • 19
18

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
    }
}
cutiko
  • 7,465
  • 3
  • 38
  • 48
6

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>
Sayed Abolfazl Fatemi
  • 3,018
  • 2
  • 29
  • 40
Stack Fox
  • 491
  • 5
  • 12