152

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.

Mark Rotteveel
  • 82,132
  • 136
  • 114
  • 158
Rasool Ghana
  • 2,273
  • 3
  • 16
  • 31
  • 5
    @RasoolGhana - Have a look at this link: https://medium.com/halcyon-mobile/implementing-googles-refreshed-modal-bottom-sheet-4e76cb5de65b – Mohit Charadva May 29 '18 at 13:09

20 Answers20

308

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.

javiCabanas
  • 3,233
  • 1
  • 10
  • 8
  • 2
    It 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 – Ivan Shafran Jun 30 '18 at 12:47
  • 1
    Crashes on android api 17 – Morteza Rastgoo May 11 '19 at 12:14
  • 1
    I 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 about `bottomsheet_rounded_background` & `AppBottomSheetStyle` – hmac Jan 06 '20 at 15:41
  • 7
    Note if you specify a background on the root view then this will override this setting – hmac Jan 06 '20 at 15:51
  • 1
    Can 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 – Code Wiget Mar 27 '20 at 21:32
  • Thanks. Works great! – Emil Mammadov Apr 04 '20 at 17:24
  • Thank you bro, it works and I love you forever dear stranger – MFQ Jun 10 '20 at 12:16
  • 4
    make sure you don’t have any background on root element of your sheet layout! – MMK Sep 16 '20 at 10:50
  • 3
    So many steps just to add rounded corners....Thanks for posting this though. – DIRTY DAVE Nov 19 '20 at 09:36
  • If you are using a toolbar on the top in BottomSheetDialogFragment then rounded corners won't show up. – Vikas Patidar Mar 05 '21 at 18:14
131

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>

enter image description here


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;
  }
Gabriele Mariotti
  • 192,671
  • 57
  • 469
  • 489
  • @Tadhg Use 1.1.0-beta01 – Gabriele Mariotti Nov 05 '19 at 05:57
  • Oh 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. – Tadhg Nov 05 '19 at 09:43
  • @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. – Gabriele Mariotti Nov 19 '19 at 23:24
  • 1
    I have reported this issue: https://issuetracker.google.com/issues/144859239 If anyone has any further findings or solution for the issue, please reply. Thanks! – androidguy Nov 20 '19 at 22:20
  • 5
    I'm getting this error and crash on v1.1.0-beta02 `Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior` – hkchakladar Jan 06 '20 at 19:33
  • 4
    It doesn't work if bottom sheet dialog is expanded. Any idea? – José Carlos Feb 10 '20 at 13:21
  • In my case, I have had to override shapeAppearance. – José Carlos Feb 10 '20 at 13:55
  • @JoséCarlos In the expanded state it doesn't work because it is a default behavior. (https://github.com/material-components/material-components-android/pull/437). I updated the answer with a workaround if you want to override the default. – Gabriele Mariotti May 30 '20 at 13:17
  • 1
    This is neat, but it doesn't seem to work on my end. – Neon Warge Jun 24 '20 at 02:26
  • 1
    Have found a way to have rounded corners even in expanded state with 1.1.0 version. Just added transparent _backgroundTint_. `` – Alex_297 Jun 29 '20 at 20:53
  • 6
    This was the perfect and latest answer. I need to mark this as answer – Vikas Acharya Jun 30 '20 at 05:46
  • This had not worked for me. After a invalidating cache and restarting android studio it worked all of a sudden. – Sourabh Aug 23 '20 at 06:36
  • 1
    I 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. – necavit Dec 18 '20 at 16:59
  • 1
    this solution is also working with `com.google.android.material:material:1.3.0` – Randunu.KSW May 02 '21 at 06:49
51

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();
Badr
  • 1,621
  • 1
  • 18
  • 26
32

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);
      }

      ...
    }
zhimin
  • 329
  • 3
  • 5
13

It worked for me

create a shape 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" />

add below styles

<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 class DialogFragment, method override getTheme also return Yourself style.

@Override
public int getTheme() {
    return R.style.AppBottomSheetDialogTheme;
}
Mohamad
  • 151
  • 1
  • 7
12

If you use the last version of material component you just have to override ShapeAppearance.MaterialComponents.LargeComponent (as the bottom sheet use this shape) and set the value you want like :

 <style name="ShapeAppearance.YourApp.LargeComponent" parent="ShapeAppearance.MaterialComponents.LargeComponent">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">12dp</item>
 </style>

And then set in your app style :

<item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.YourApp.LargeComponent</item>

The solution of Gabriele Mariotti is similar and works too but this one is simpler.

Benjamin Ledet
  • 522
  • 1
  • 4
  • 12
  • As compared to other it is a much better solution, because most of the solution out there is base on set custom drawable – d-feverx Jun 20 '20 at 06:55
  • 1
    Looks nice. Does this also apply to `BottomSheetDialog` ? – Jaden Gu Jul 15 '20 at 02:12
  • 1
    Note 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. – nitinkumarp Sep 17 '20 at 12:37
10

I was checking the same thing today and yes you were right about following code

this.getDialog().getWindow().setBackgroundDrawableResource(R.drawable.charge_layout_background);

this applies to fragment background, so instead you should get the bottomsheet view from dialog window and change the background here is the code

 @SuppressLint("RestrictedApi")
    @Override
    public void setupDialog(Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        View rootView = getActivity().getLayoutInflater().inflate(R.layout.view_member_info,null,false);
        unbinder = ButterKnife.bind(this, rootView);
        adjustUIComponents();
        dialog.setContentView(rootView);
        FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet);
        bottomSheet.setBackgroundResource(R.drawable.container_background);
    }

here bottomsheet is the actual view you want to change.

Aashish Bhatnagar
  • 2,781
  • 2
  • 21
  • 36
9

Answer by Koma Yip from another question worked for me, you should try it.

Create a xml in drawable , say dialog_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white"/>
    <corners android:radius="30dp" />
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp" />
</shape>

put this in your layout xml root node:

set it as the background in your layout xml

android:background="@drawable/dialog_bg"

and in onCreateView() put this:

set the background of your dialog to transparent

dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Variag
  • 692
  • 7
  • 20
  • This should be the right solution because it works for all DialogFragments without jumping through hoops. – jssingh Apr 13 '18 at 18:00
  • 3
    **For 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 Apr 29 '18 at 15:22
  • Adding 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. – Nick Dev Apr 29 '18 at 15:39
  • 1
    @NickDev Post new question if you think this solution does not apply to your code and maybe we'll find a solution. – Variag Apr 30 '18 at 16:00
  • @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. – Nick Dev May 01 '18 at 02:51
8
  1. Create a shape drawable .. which we will use as background for bottom sheet . Provide the appropriate value for radius of top left and right corner .

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners
            android:topLeftRadius="24dp"
            android:topRightRadius="24dp" />
        <padding android:top="2dp" />
        <solid android:color="@color/white" />
    </shape>
    
  2. Now create style for " Bottom sheet dialog fragment "

    <style name="BottomSheet" parent="@style/Widget.Design.BottomSheet.Modal">
            <item name="android:background">@drawable/drawable_bottomsheet_background</item>
        </style>
    
        <style name="BaseBottomSheetDialog" parent="@style/Theme.Design.Light.BottomSheetDialog">
            <item name="android:windowIsFloating">false</item>
            <item name="bottomSheetStyle">@style/BottomSheet</item>
        </style>
    
        <style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />
    
  3. Now create a custom class that will extend BottomSheetDilogFragment ,where you provide your style .

    open class CustomRoundBottomSheet : BottomSheetDialogFragment() {
    
        override fun getTheme(): Int = R.style.BottomSheetDialogTheme
    
        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme)
    
    }
    
  4. Now use this class wherever you want to have round corner bottom sheet . eg

    class BottomSheetSuccess : CustomRoundBottomSheet() {
    
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.bottomsheet_shopcreate_success, container, false)
        }
    
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
        }
    
    } 
    
EpicPandaForce
  • 71,034
  • 25
  • 221
  • 371
Mini Chip
  • 771
  • 6
  • 9
4

This answer is only for the issue of setting the background color to Color.TRANSPARENT after setting up a drawable with rounded background to the layout.

None of the answer worked for me to set the background color to Color.TRANSPARENT except overriding setupDialog() solution:

@Override
public void setupDialog(Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View contentView = View.inflate(getContext(), 
R.layout.fragment_bottom_sheet, null);
    dialog.setContentView(contentView);
    ...
    ((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
}

BUT the contentView you set for dialog here is not the view you get in onViewCreated() when inflating in onCreateView(). It breaks the standard flow, so may issue troubles like you can't use View Bindings - Kotlin Android Extensions in onViewCreated()

So I tweak a bit to set the background in onActivityCreated():

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    (view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
  }

Hope this help who got same trouble

DuDu
  • 311
  • 2
  • 7
4

I know this question already has an accepted answer. I'd like to document the problems I went through and how I finally got it working so it is useful for someone on the future.

Firstly, I was using Theme.AppCompat.Light.DarkActionBar as the parent for our AppTheme. This meant @Gabriele Mariotti solution kept crashing with the error Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior. I fixed this by simply changing the parent to Theme.MaterialComponents.Light.DarkActionBar. This did not affect our theme in any way but the RTE was gone. You can also fix this issue by simply including the require items to your style. But I didn't bother figuring out which styles were required by BottomSheetBehavior.

Secondly, try as I might, but I couldn't get the actual Frame layout (which was the BottomSheetDialogFragment) uses to have round corners. I realized that setting this to an image Drawable worked but not with a shape or a @null. Turns out, it was because the LinearLayout I was using had a background defined. This was overriding any background in the style. Removing that finally resulted in rounded corners.

Also, I didn't require any background shape to be set to round the corners. @Gabriele Mariotti's solution worked as soon as I made the above changes. However, to set the background colour what I wanted it to be, I had to override the "backgroundTint" item.

PS: I'm new to Android dev, and am maintaining an old App that was made for internal use in our College. I'm not all that familiar with Android's layout system or with the material library. I guess that's why it took me 3 days to figure this out. I hope this is useful to someone in the future.

abhijeetviswa
  • 113
  • 2
  • 11
  • Thanks! You saved my day explaining the change needed from Theme.AppCompat... to Theme.MaterialComponents... It was driving me crazy – jaumebd Feb 18 '21 at 21:24
3

Simplistic solution:

class TopRoundedCornersFragment : BottomSheetDialogFragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setStyle(STYLE_NORMAL, R.style.AppBottomSheetDialogTheme)
    }
}

In styles.xml

<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@drawable/bottom_sheet_dialog_bg</item>
</style>

<style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/BottomSheetStyle</item>
</style>

Last, create a top rounded corner drawable resource (bottom_sheet_dialog_bg.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@android:color/white" />
    <corners
        android:topLeftRadius="4dp"
        android:topRightRadius="4dp" />

</shape>
DYS
  • 1,918
  • 16
  • 27
  • It 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)` – mafortis Feb 24 '21 at 03:20
1

Add these two methods in your BottomsheetDialogFragment class.

public void setDialogBorder(Dialog dialog) {
        FrameLayout bottomSheet = (FrameLayout) dialog.getWindow().findViewById(android.support.design.R.id.design_bottom_sheet);
        bottomSheet.setBackground(new ColorDrawable(Color.TRANSPARENT));
        setMargins(bottomSheet, 10, 0, 10, 20);
    }

    private void setMargins(View view, int left, int top, int right, int bottom) {
        if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
            p.setMargins(left, top, right, bottom);
            view.requestLayout();
        }
    }

Now call setDialogBorder(dialog) method in setupDialog() method of your BottomsheetDialogFragment class.

Now create a shape file in your drawable folder.

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="20dp" />

    <solid android:color="@color/white" />
    <stroke
        android:width="1dp"
        android:color="@color/transparent" />
</shape>

Now set background for the parent viewgroup dialog view in xml file.

android:background="@drawable/round_border_white"

Done!!

1

add shape with rounded corner, make it background for your root layout

<?xml version="1.0" encoding="utf-8" ?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
 <corners
    android:topLeftRadius="@dimen/padding_margin_16_dp"
    android:topRightRadius="@dimen/padding_margin_16_dp" />
 <solid android:color="@color/white" />
</shape>

make background transparent on your BottomSheetDialogFragment

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    (view?.parent as View).setBackgroundColor(Color.TRANSPARENT)
}

its work for Contraintlayout, Framelyaout, Linearlayout, Relativelayout.

1

Complete Solution:

Add below style attribute to style.xml.

<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_background</item>
</style>

Then use AppBottomSheetDialogTheme to create a bottom sheet dialog from your code.

private fun openBottomSheetTermsCondition() {
    val mBottomSheetDialog = BottomSheetDialog(requireContext(),R.style.AppBottomSheetDialogTheme)
    val sheetView = layoutInflater.inflate(R.layout.bottom_sheet_travel_advice_terms, null)
    mBottomSheetDialog.setContentView(sheetView)
    sheetView.tv_head.setOnClickListener {
        mBottomSheetDialog.dismiss()
    }

    sheetView.webView.loadDataWithBaseURL(null,getString(R.string.privacy_policy_body_html),"text/html", "utf-8", null)
    mBottomSheetDialog.show()
}

I use the below drawable to round the bottom sheet background.

    <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:topLeftRadius="@dimen/bottom_sheet_corner_radius"
        android:topRightRadius="@dimen/bottom_sheet_corner_radius" />
    <solid android:color="@color/white" />
</shape>

Bottom sheet xml bottom_sheet_travel_advice_terms.xml

    <?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView 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"
    app:behavior_hideable="false"
    app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
    app:cardCornerRadius="@dimen/spacing_normal"
    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/spacing_small">

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/begin_horizontal_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_begin="@dimen/activity_vertical_margin" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/begin_vertical_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="@dimen/activity_horizontal_margin" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/end_vertical_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_end="@dimen/activity_horizontal_margin" />

        <View
            android:id="@+id/sheet_header_shadow"
            android:layout_width="match_parent"
            android:layout_height="@dimen/spacing_tiny"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:background="@drawable/bottom_sheet_header_shadow"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/tv_head"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:drawablePadding="@dimen/spacing_normal"
            android:fontFamily="sans-serif-medium"
            android:gravity="start"
            android:padding="@dimen/spacing_small"
            android:text="@string/term_and_condition"
            android:textColor="@color/greyish_brown"
            android:textSize="20sp"
            app:drawableLeftCompat="@drawable/ic_close_black_24dp"
            app:layout_constraintEnd_toEndOf="@id/end_vertical_guideline"
            app:layout_constraintStart_toStartOf="@id/begin_vertical_guideline"
            app:layout_constraintTop_toBottomOf="@+id/begin_horizontal_guideline" />

        <View
            android:id="@+id/line_separation"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="@dimen/spacing_small"
            android:background="@color/blue_gray"
            app:layout_constraintTop_toBottomOf="@+id/tv_head" />

        <WebView
            android:id="@+id/webView"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="@id/end_vertical_guideline"
            app:layout_constraintStart_toStartOf="@id/begin_vertical_guideline"
            app:layout_constraintTop_toBottomOf="@id/line_separation" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>
Shihab Uddin
  • 4,947
  • 2
  • 43
  • 69
1

Bottom Sheet Dialog with Curved shape and peek height

    <!-- BottomSheet Dialog -->
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/CustomBottomSheet</item>

</style>


<style name="CustomBottomSheet" parent="Widget.MaterialComponents.BottomSheet">
    <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item>
    <item name="behavior_peekHeight">420dp</item>
</style>

<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">20dp</item>
    <item name="cornerSizeTopLeft">20dp</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>

</style>
0

Another way to fix this issue is to extend BottomSheetDialog and create a custom class which suits your needs. You can do the same for layout xml file, and add background or any other customizations needed. This also has a benefit that you'll not be dependent on the id names used by Android(android.support.design.R.id.design_bottom_sheet), while changing the background (though the change of id name rarely happens AFAIK).

gaurav jain
  • 3,040
  • 3
  • 27
  • 44
0

Create a custom drawable with rounded corner and set it as background of your BottomSheetDialogFragment's layout root

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<solid android:color="@color/colorPrimary" />

<corners
    android:bottomLeftRadius="0dp"
    android:bottomRightRadius="0dp"
    android:topLeftRadius="12dp"
    android:topRightRadius="12dp" />

</shape>

And then simply add the below code to your BottomSheetDialogFragment class

@Override
public void setupDialog(Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View contentView = View.inflate(getContext(), 
R.layout.fragment_bottom_sheet, null);
    dialog.setContentView(contentView);

    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent())
            .getLayoutParams();
    CoordinatorLayout.Behavior behavior = params.getBehavior();
    ((View) contentView.getParent()).setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
}

You can even play with the params to set margin like below

params.setMargins(50, 0, 50, 0);
Darshna Desai
  • 136
  • 1
  • 5
0

You have to change the bottom sheet theme to achieve the top round layout

Create a custom drawable background_bottom_sheet_dialog_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
    <corners
       android:topLeftRadius="8dp"
        android:topRightRadius="8dp" />
    <padding android:top="0dp" />
    <solid android:color="@color/white" />
</shape>

Then override bottomSheetDialogTheme on styles.xml using the drawable as background:

<!--Bottom sheet-->
<style name="BottomSheet" parent="@style/Widget.Design.BottomSheet.Modal">
    <item 
    name="android:background">@drawable/background_bottom_sheet_dialog_fragment
    </item>
</style>

<style name="BaseBottomSheetDialog" 
    parent="@style/Theme.Design.Light.BottomSheetDialog">
    <item name="android:windowIsFloating">false</item>
    <item name="bottomSheetStyle">@style/BottomSheet</item>
</style>

<style name="BottomSheetDialogTheme" parent="BaseBottomSheetDialog" />

This will change the background layout of your bottom sheet

BottomSheetDialog

class SheetFragment() : BottomSheetDialogFragment() {

    lateinit var binding: SheetFragmentBinding;

  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog;
    val view = View.inflate(context, R.layout.fragment_bottom_sheet, null);

    binding = DataBindingUtil.bind(view)!!;
    binding.viewModel = SheetFragmentVM();

    dialog.setContentView(view);

    var bottomSheetBehavior = BottomSheetBehavior.from(view.parent as View);
    bottomSheetBehavior.setPeekHeight(BottomSheetBehavior.PEEK_HEIGHT_AUTO);

    bottomSheetBehavior.setBottomSheetCallback(object : 
     BottomSheetBehavior.BottomSheetCallback() {
        override fun onStateChanged(bottomSheet: View, newState: Int) {
            if (BottomSheetBehavior.STATE_EXPANDED == newState) {
               // do on STATE_EXPANDED
            }
            if (BottomSheetBehavior.STATE_COLLAPSED == newState) {
                // do on STATE_COLLAPSED
            }

            if (BottomSheetBehavior.STATE_HIDDEN == newState) {
                dismiss()

            }
        }

        override fun onSlide(bottomSheet: View, slideOffset: Float) {
           // do on slide
        }
    })

    return dialog
}
Atul
  • 899
  • 10
  • 7
0

setupDialog() is RestrictedApi. The simplest solution that works as of material:1.3.0-beta01 without touching themes:

res/drawable/bs_background:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners
    android:topLeftRadius="16dp"
    android:topRightRadius="16dp" />
  <solid android:color="@color/dayNightBackground" />
</shape>
public class MyBsDialogFrag extends BottomSheetDialogFragment {

@Override
  public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((View) view.getParent()).setBackgroundResource(R.drawable.bs_background);
  }

}
Irfan Latif
  • 356
  • 2
  • 4
  • 14