What I'm trying to achieve is something like Instagram in-app web browser, used when you click an ad:
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 :
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.
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".
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.
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; }
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
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;
}
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
}
}
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
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>
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
I used such way:
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 >
just add below line of code
bottomSheetDialog.getBehavior().setState(BottomSheetBehavior.STATE_EXPANDED);
and layout should be inside NestedScrollView
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With