Round corner for BottomSheetDialogFragment
Solution 1
Create a custom drawable rounded_dialog.xml
:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white"/>
<corners android:topLeftRadius="16dp"
android:topRightRadius="16dp"/>
</shape>
Then override bottomSheetDialogTheme
on styles.xml
using the drawable as background:
<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/rounded_dialog</item>
</style>
This will change all the BottomSheetDialogs of your app.
Solution 2
With the new Material Component library you can customize the shape of your component using the shapeAppearanceOverlay
attribute in your style (Note: it requires at least the version 1.1.0)
Just use the BottomSheetDialogFragment
overriding the onCreateView
method and then define your custom style for Bottom Sheet Dialogs.
Define the bottomSheetDialogTheme
attribute in styles.xml
in your app theme:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
....
<item name="bottomSheetDialogTheme">@style/CustomBottomSheetDialog</item>
</style>
Then just define your favorite shape with shapeAppearanceOverlay
<style name="CustomBottomSheetDialog" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
<item name="bottomSheetStyle">@style/CustomBottomSheet</item>
</style>
<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
<item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item>
</style>
<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">16dp</item>
<item name="cornerSizeTopLeft">16dp</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>
You can obtain the same behavior overriding this method in your BottomSheetDialogFragment
(instead of adding the bottomSheetDialogTheme
in your app theme):
@Override public int getTheme() {
return R.style.CustomBottomSheetDialog;
}
In this case you are using this themeOverlay only in the single BottomSheetDialogFragment
and not in all the app.
Important note about the EXPANDED STATE:
In the expanded state the BottomSheet has flat corners . You can check the official comment in github repo:
Our design team is strongly opinionated that rounded corners indicate scrollable content while flat corners indicate that there is no additional content. As such, they do no want us to add this change with fitToContents.
This behavior is provided by the BottomSheetBehavior
and it is impossible to override it.
However there is a workaround -> DISCLAIMER: it can stop to work in the next releases !!
You can add a BottomSheetCallback
in the BottomSheetDialogFragment
:
@NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
((BottomSheetDialog)dialog).getBehavior().addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
//In the EXPANDED STATE apply a new MaterialShapeDrawable with rounded cornes
MaterialShapeDrawable newMaterialShapeDrawable = createMaterialShapeDrawable(bottomSheet);
ViewCompat.setBackground(bottomSheet, newMaterialShapeDrawable);
}
}
@Override public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
return dialog;
}
@NotNull private MaterialShapeDrawable createMaterialShapeDrawable(@NonNull View bottomSheet) {
ShapeAppearanceModel shapeAppearanceModel =
//Create a ShapeAppearanceModel with the same shapeAppearanceOverlay used in the style
ShapeAppearanceModel.builder(getContext(), 0, R.style.CustomShapeAppearanceBottomSheetDialog)
.build();
//Create a new MaterialShapeDrawable (you can't use the original MaterialShapeDrawable in the BottoSheet)
MaterialShapeDrawable currentMaterialShapeDrawable = (MaterialShapeDrawable) bottomSheet.getBackground();
MaterialShapeDrawable newMaterialShapeDrawable = new MaterialShapeDrawable((shapeAppearanceModel));
//Copy the attributes in the new MaterialShapeDrawable
newMaterialShapeDrawable.initializeElevationOverlay(getContext());
newMaterialShapeDrawable.setFillColor(currentMaterialShapeDrawable.getFillColor());
newMaterialShapeDrawable.setTintList(currentMaterialShapeDrawable.getTintList());
newMaterialShapeDrawable.setElevation(currentMaterialShapeDrawable.getElevation());
newMaterialShapeDrawable.setStrokeWidth(currentMaterialShapeDrawable.getStrokeWidth());
newMaterialShapeDrawable.setStrokeColor(currentMaterialShapeDrawable.getStrokeColor());
return newMaterialShapeDrawable;
}
Solution 3
The BottomSheetDialog
is setting a default white background color , this is why the corners are not visible, In order to show them you need to make the background of the dialog transparent by overriding the style of the BottomSheetDialog
.
Define this style In your res/values/styles/styles.xml
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
And set this style to your BottomSheetDialog
View view = getLayoutInflater().inflate(R.layout.chooser_bottom_sheet, null);
BottomSheetDialog dialog = new BottomSheetDialog(this,R.style.BottomSheetDialog); // Style here
dialog.setContentView(view);
dialog.show();
Solution 4
create a shape named rounded_corners_shape
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp"/>
<solid android:color="@color/white"/>
</shape>
define a 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/rounded_corners_shape</item>
</style>
use this style on your custom BottomSheetDialogFragment like this, it will be work!
public class CustomDialogFragment extends BottomSheetDialogFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(STYLE_NORMAL, R.style. AppBottomSheetDialogTheme);
}
...
}
Solution 5
This worked for me.
Create a background drawable (e.g. named shape_rounded_dialog
):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/color_white" />
<corners android:topLeftRadius="16dp"
android:topRightRadius="16dp" />
</shape>
Add the styles below:
<style name="AppBottomSheetDialogTheme"
parent="Theme.MaterialComponents.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/CustomBottomSheetStyle</item>
</style>
<style name="CustomBottomSheetStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@drawable/shape_rounded_dialog</item>
</style>
In your DialogFragment
, override the method getTheme()
to return your style.
@Override
public int getTheme() {
return R.style.AppBottomSheetDialogTheme;
}
Related videos on Youtube
Russell Ghana
Updated on April 11, 2022Comments
-
Russell Ghana about 2 years
I have a custom BttomSheetDialogFragment and I want to have round corners in top of Bottom View
This is my Custom class that inflates my layout that I want to appear from bottom
View mView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.charge_layout, container, false); initChargeLayoutViews(); return mView; }
and also I have this XML resource file as background:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <corners android:topRightRadius="35dp" android:topLeftRadius="35dp" /> <solid android:color="@color/white"/> <padding android:top="10dp" android:bottom="10dp" android:right="16dp" android:left="16dp"/> </shape>
The problem is, when I set this resource file as background of my Layout's root element, the corners still are not rounded.
I can't use below code:
this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);
Because it overrides the default background of BottomSheetDialog and there won't be any semi-transparent gray color above my Bottom View.
-
Mohit Charadva almost 6 years@RasoolGhana - Have a look at this link: medium.com/halcyon-mobile/…
-
-
jssingh about 6 yearsThis should be the right solution because it works for all DialogFragments without jumping through hoops.
-
Nick Dev about 6 yearsFor me, there are still white corners behind my rounded corners. So when I change the color of my drawable to red, your code works correctly and creates a rounded red rectangle, but behind that there is still a default white rectangle. The "dialog.getWindow().setBackgroundDrawable..." code you wrote changes the color of the entire "darkened" area above my dialog, but again, it misses those two little corners. Do you know what could be causing this issue?
-
Nick Dev about 6 yearsAdding on to my comment above, I should note that I had to change the code in onCreateView() to "getDialog().getWindow()..." in order for my code to run. Perhaps this is why it doesn't work for me.
-
Variag about 6 years@NickDev Post new question if you think this solution does not apply to your code and maybe we'll find a solution.
-
Nick Dev about 6 years@Variag Thanks for reaching out; I actually came up with a cheap workaround where I cover the default bottom sheet modal dialog with a rectangle that is the same color as the darkened area behind it. Then I added a second rectangle with rounded corners on top of that. It's not ideal, but it looks great! I appreciate the help nonetheless.
-
Ivan Shafran almost 6 yearsIt works for me. Also I noticed it depends on layout root element. Firstly I had cardview as root (cause I tried another way to round corners), then I changed it to linear layout and now it works perfectly
-
tmm1 almost 6 yearsWhich view do you use with setMargins?
-
DalveerSinghDaiya almost 6 yearsFrameLayout bottomSheet ; This one defined in setDialogBorder() method. This actually is the default view for the bottom sheet dialog in android. It will work fine.
-
Morteza Rastgoo about 5 yearsCrashes on android api 17
-
UditS almost 5 yearsIt would be helpful if you add some clarification along with the code.
-
DYS almost 5 yearsThis is the right place to set theme for
Fragment
s. -
Gabriele Mariotti over 4 years@Tadhg Use 1.1.0-beta01
-
Tadhg over 4 yearsOh whoops, I’m on 1.2.0alpha02 in order to support the new wonky “spinners”. I was able to get this code working on 1.2.0.02 but it doesn’t utilise the new shape component stuff.
-
Gabriele Mariotti over 4 years@androidguy thanks for feedback. I have to check it but it seems a bug of the library. In any case I don't work in the material components team.
-
androidguy over 4 yearsI have reported this issue: issuetracker.google.com/issues/144859239 If anyone has any further findings or solution for the issue, please reply. Thanks!
-
Kirill Starostin over 4 yearsThe only way i got this working. Btw i'm using
BottomSheetDialogFragment
so that logic is in theonCreateDialog
method -
hmac over 4 yearsI wouldn't use
rounded_dialog
&AppModalStyle
names with a background where only the top corners are rounded, as you would only expect to use such a background with a bottom sheet style. How aboutbottomsheet_rounded_background
&AppBottomSheetStyle
-
hmac over 4 yearsNote if you specify a background on the root view then this will override this setting
-
hkchakladar over 4 yearsI'm getting this error and crash on v1.1.0-beta02
Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior
-
José Carlos over 4 yearsIt doesn't work if bottom sheet dialog is expanded. Any idea?
-
José Carlos over 4 yearsIn my case, I have had to override shapeAppearance. <style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet"> <item name="shapeAppearance">@style/CustomShapeAppearanceBottomSheetDialog</item> <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item> </style>
-
Luke Needham about 4 yearsBetter than the accepted answer, because this way you can have different backgrounds on different BottomSheetDialogs
-
Code Wiget about 4 yearsCan this be done without using a theme? When I use
Theme.AppCompat.Light.NoActionBar
it causes all of my UI components to change colors and I can't override them -
Emil Mammadov about 4 yearsThanks. Works great!
-
Arnold Brown almost 4 yearsNow curve visible, but a transparent color throughout the screen on touch only the white color on bottom dialog is visible @Badr any corrrection?
-
Gabriele Mariotti almost 4 years@JoséCarlos In the expanded state it doesn't work because it is a default behavior. (github.com/material-components/material-components-android/pull/…). I updated the answer with a workaround if you want to override the default.
-
MFQ almost 4 yearsThank you bro, it works and I love you forever dear stranger
-
d-feverx almost 4 yearsAs compared to other it is a much better solution, because most of the solution out there is base on set custom drawable
-
Neon Warge almost 4 yearsThis is neat, but it doesn't seem to work on my end.
-
Alex_297 almost 4 yearsHave found a way to have rounded corners even in expanded state with 1.1.0 version. Just added transparent backgroundTint.
<style name="CustomBottomSheetDialog" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog"> <item name="bottomSheetStyle">@style/CustomBottomSheet</item> <item name="android:backgroundTint">@color/transparent</item> </style>
-
Vikas Acharya almost 4 yearsThis was the perfect and latest answer. I need to mark this as answer
-
Jaden Gu almost 4 yearsLooks nice. Does this also apply to
BottomSheetDialog
? -
Sourabh over 3 yearsThis had not worked for me. After a invalidating cache and restarting android studio it worked all of a sudden.
-
MMK over 3 yearsmake sure you don’t have any background on root element of your sheet layout!
-
nitinkumarp over 3 yearsNote to all: Using this answer will cause all component using
ShapeAppearance.MaterialComponents.LargeComponent
to have same cornerSize and family, not just Bottom Sheet. Check your style requirement and decide if you want change appearance for all component or just individual component or widget. -
Prateek Gupta over 3 yearsThat's the solution I was looking for, Totally hack free.
-
DIRTY DAVE over 3 yearsSo many steps just to add rounded corners....Thanks for posting this though.
-
necavit over 3 yearsI must "inject" the theme by overriding
getTheme()
, because our app theme does not yet inherit from any Material theme. However, I am also facing an exception "Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior", like @hkchakladar commented. Has anyone else faced this issue and got it solved? It feels like some theming attributes are missing, but since we're using a Theme.Overlay... I find that weird. Still struggling with it after setting a bunch of Material theme attributes on the overlay. -
Sandy over 3 yearsSolution with simple understandable explanation kudos @Badr
-
jaumebd about 3 yearsThanks! You saved my day explaining the change needed from Theme.AppCompat... to Theme.MaterialComponents... It was driving me crazy
-
mafortis about 3 yearsIt also needs background transparent on
onViewCreated
which clears out background under radiused corners and you can actually see the corners(view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
-
Vikas Patidar about 3 yearsIf you are using a toolbar on the top in BottomSheetDialogFragment then rounded corners won't show up.
-
Randunu.KSW about 3 yearsthis solution is also working with
com.google.android.material:material:1.3.0
-
Burak over 2 yearsThis worked for me, thanks!
-
Naimul Kabir over 2 yearsThanks a lot, man. This is the latest solution as of 26 September 2021.
-
Kenny over 2 yearsDoesn't seem to work anymore in 1.4 :/
-
Kenny over 2 yearsThis worked to get the dialog shape as you'd like, but it loses all the other setup attributes from the theme as well. Just FYI
-
Rick Robin over 2 yearsSimple and effective
-
Maher Abuthraa over 2 yearsElegant solution👍🏼
-
c-an over 2 yearsthis loses dialog's behaviour
-
Zain over 2 years@c-an Thanks for this; I just enhanced the answer with a different approach; hopefully it helps
-
Najib.Nj over 2 yearsPerfect answer working like charm !! :)
-
Tuan Dao over 2 yearsthis isn't work if you expand bottom sheet
-
Ankit Gupta over 2 yearsNot working as of Feb 2021
-
Vishnu about 2 yearsThe only one that worked for me. Thanks Badr.