183

我有一个自定义 BttomSheetDialogFragment 并且我想在底部视图顶部有圆角

这是我的自定义类,它膨胀了我想从底部显示的布局

View mView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.charge_layout, container, false);
    initChargeLayoutViews();
    return mView;
}

而且我有这个 XML 资源文件作为背景:

<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>

问题是,当我将此资源文件设置为我的布局根元素的背景时,角落仍然没有圆角。

我不能使用下面的代码:

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

因为它覆盖了 BottomSheetDialog 的默认背景,并且我的底部视图上方不会有任何半透明的灰色。

4

25 回答 25

360

创建自定义可绘制对象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>

然后覆盖bottomSheetDialogTheme使用styles.xmldrawable作为背景:

<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>

这将更改应用程序的所有 BottomSheetDialogs。

于 2018-06-19T13:37:34.340 回答
194

使用新的材料组件库,您可以使用样式中的属性自定义组件的形状(注意:它至少需要1.1.0版本)shapeAppearanceOverlay

只需使用BottomSheetDialogFragment覆盖该onCreateView方法,然后为底部工作表对话框定义您的自定义样式。

在您的应用主题中定义bottomSheetDialogTheme属性:styles.xml

  <!-- 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>

然后只需定义您最喜欢的形状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>

在此处输入图像描述


BottomSheetDialogFragment您可以在您的(而不是bottomSheetDialogTheme在您的应用程序主题中添加)获得覆盖此方法的相同行为:

@Override public int getTheme() {
    return R.style.CustomBottomSheetDialog;
  }

在这种情况下,您仅在单个BottomSheetDialogFragment应用程序中而不是在所有应用程序中使用此 themeOverlay。


关于扩展状态的重要说明

在展开状态下,BottomSheet具有平角您可以在github repo中查看官方评论:

我们的设计团队强烈认为圆角表示可滚动的内容,而平角表示没有额外的内容。因此,他们不希望我们使用 fitToContents 添加此更改。

此行为由 提供,BottomSheetBehavior并且无法覆盖它。
但是有一个解决方法->免责声明:它可以在下一个版本中停止工作!

您可以BottomSheetCallbackBottomSheetDialogFragment:

  @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;
  }
于 2019-08-23T13:20:18.930 回答
66

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();
于 2018-06-01T14:33:24.127 回答
38

创建一个名为 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>

定义风格

  <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>

像这样在您的自定义 BottomSheetDialogFragment 上使用此样式,它将起作用!

 public class CustomDialogFragment extends BottomSheetDialogFragment {
      @Override
      public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style. AppBottomSheetDialogTheme);
      }

      ...
    }
于 2019-06-06T08:48:52.987 回答
20

这对我有用。

创建一个背景可绘制对象(例如命名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>

添加以下样式:

<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>

在您的DialogFragment中,覆盖该方法getTheme()以返回您的样式。

@Override
public int getTheme() {
    return R.style.AppBottomSheetDialogTheme;
}
于 2020-08-22T14:53:43.820 回答
12

如果您使用最后一个版本的材料组件,您只需覆盖ShapeAppearance.MaterialComponents.LargeComponent(因为底部工作表使用此形状)并设置您想要的值,例如:

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

然后设置您的应用样式:

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

Gabriele Mariotti 的解决方案是类似的并且也有效,但这个更简单。

于 2019-11-19T14:16:21.227 回答
10

Koma Yip另一个问题的回答对我有用,你应该试试。

在 drawable 中创建一个 xml,比如 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>

把它放在你的布局 xml 根节点中:

将其设置为布局 xml 中的背景

android:background="@drawable/dialog_bg"

onCreateView()把这个:

将对话框的背景设置为透明

dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
于 2018-01-10T08:43:02.660 回答
10

我今天检查了同样的事情,是的,您对以下代码是正确的

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

这适用于片段背景,因此您应该从对话框窗口获取底部视图并更改背景这里是代码

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

这里的底页是您要更改的实际视图。

于 2017-11-23T10:32:56.657 回答
9
  1. 创建一个可绘制的形状 .. 我们将用作底页的背景。为左上角和右上角的半径提供适当的值。

    <?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. 现在为“底部工作表对话框片段”创建样式

    <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. 现在创建一个自定义类,它将扩展您提供样式的 BottomSheetDilogFragment 。

    open class CustomRoundBottomSheet : BottomSheetDialogFragment() {
    
        override fun getTheme(): Int = R.style.BottomSheetDialogTheme
    
        override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = BottomSheetDialog(requireContext(), theme)
    
    }
    
  4. 现在在任何你想有圆角底片的地方使用这个类。例如

    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)
        }
    
    } 
    
于 2018-08-21T07:14:26.013 回答
6

简单的解决方案:

class TopRoundedCornersFragment : BottomSheetDialogFragment() {

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

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

在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>

最后,创建一个顶部圆角可绘制资源(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>
于 2020-12-14T07:26:36.720 回答
4

此答案仅针对在为Color.TRANSPARENT布局设置圆形背景的可绘制对象后设置背景颜色的问题。

Color.TRANSPARENT除了覆盖解决方案之外,没有一个答案对我有用,可以将背景颜色设置为setupDialog()

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

但是你在contentView这里设置的对话框不是view你在onViewCreated()充气时进入的onCreateView()。它打破了标准流程,因此可能会出现您无法使用的问题View Bindings- Kotlin Android ExtensionsinonViewCreated()

所以我稍微调整一下以设置背景onActivityCreated()

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

希望对遇到同样麻烦的人有所帮助

于 2018-06-06T09:47:39.983 回答
4

我知道这个问题已经有一个公认的答案。我想记录我遇到的问题以及我最终是如何让它工作的,以便对未来的人有用。

首先,我Theme.AppCompat.Light.DarkActionBar用作我们的AppTheme. 这意味着@Gabriele Mariotti 解决方案不断因错误而崩溃Could not inflate Behavior subclass com.google.android.material.bottomsheet.BottomSheetBehavior。我通过简单地将父级更改为Theme.MaterialComponents.Light.DarkActionBar. 这并没有以任何方式影响我们的主题,但 RTE 已经消失了。您也可以通过简单地将所需项目包含到您的样式中来解决此问题。但是我没有费心去弄清楚BottomSheetBehavior 需要哪些样式。

其次,尽我所能尝试,但我无法获得具有圆角的实际框架布局(即 BottomSheetDialogFragment)。我意识到将其设置为图像 Drawable 有效,但不适用于形状或@null. 原来,这是因为LinearLayout我使用的定义了背景。这覆盖了风格中的任何背景。删除最终导致圆角。

此外,我不需要将任何背景形状设置为圆角。@Gabriele Mariotti 的解决方案在我进行上述更改后立即起作用。但是,要设置我想要的背景颜色,我必须覆盖“backgroundTint”项目。

PS:我是 Android 开发新手,并且正在维护一个旧应用程序,该应用程序是为我们学院内部使用而制作的。我对 Android 的布局系统或材质库不是很熟悉。我想这就是为什么我花了 3 天时间才弄清楚这一点的原因。我希望这对将来的某人有用。

于 2020-05-06T07:19:27.950 回答
3

具有弯曲形状和窥视高度的底部工作表对话框

    <!-- 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>
于 2021-05-12T06:51:28.083 回答
3

对我有用的最简单和最干净的解决方案是将以下 3 行放入我的片段类的 onViewCreated(View view, Bundle savedInstanceState) 方法中:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    View bottomSheet = (View) view.getParent();
    bottomSheet.setBackgroundTintMode(PorterDuff.Mode.CLEAR);
    bottomSheet.setBackgroundTintList(ColorStateList.valueOf(Color.TRANSPARENT));
    bottomSheet.setBackgroundColor(Color.TRANSPARENT);
}

一旦设置为片段布局的顶级视图的背景,这将允许您的自定义可绘制圆角正确显示。

本质上,这会覆盖关于颜色、tintMode 和 tintList 的默认 BottomSheetFragment 属性。

使用它,就不需要弄乱样式资源了。

于 2021-12-16T13:27:57.297 回答
1

首先,您应该创建一个可绘制的 xml 文件,其中包含一个顶部圆角的形状,随便命名。我将它命名为底部 rounded_top_shape.xml

<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"
    />

然后在你的 style.xml 添加这个

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

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

然后在您的应用主题中添加此行如下

 <style name="MyAppTheme" parent="Theme.MaterialComponents.Light.Bridge">
    <!-- this line -->
    <item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
</style>
于 2022-01-12T14:57:23.333 回答
1

在您的 BottomsheetDialogFragment 类中添加这两个方法。

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

现在在您的 BottomsheetDialogFragment 类setDialogBorder(dialog)的方法中调用方法。setupDialog()

现在在您的可绘制文件夹中创建一个形状文件。

<?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>

现在为 xml 文件中的父视图组对话框视图设置背景。

android:background="@drawable/round_border_white"

完毕!!

于 2018-03-17T09:44:45.263 回答
1

setupDialog()是 RestrictedApi。最简单的解决方案,material:1.3.0-beta01无需触及主题:

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

}
于 2020-12-31T13:52:16.847 回答
1

添加圆角形状,使其成为根布局的背景

<?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>

在您的 BottomSheetDialogFragment 上使背景透明

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

它适用于 Contraintlayout、Framelyaout、Linearlayout、Relativelayout。

于 2020-08-26T00:50:13.383 回答
1

您必须更改bottom sheet theme以实现顶轮布局

创建自定义可绘制 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>

然后使用drawable作为背景覆盖styles.xml上的bottomSheetDialogTheme:

<!--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" />

这将更改底部工作表的背景布局

底页对话框

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
}
于 2019-04-09T19:15:58.520 回答
1

步骤1:

创建一个res/drawable命名为rounded_background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners
    android:topLeftRadius="32dp"
    android:topRightRadius="32dp" />
  <solid android:color="#D81B60" />
</shape>

第2步:

创建此样式以删除对话框背景:

<style name="NoBackgroundDialogTheme" parent="Theme.AppCompat.Light.Dialog">
    <item name="android:windowBackground">@null</item>
</style>

第 3 步:

setBackgroundResource()使用& 通过覆盖getTheme()方法设置样式将可绘制对象设置为对话框的根视图

爪哇:

public class MyDialogFragment extends BottomSheetDialogFragment {

    @Override
    public int getTheme() {
        return R.style.NoBackgroundDialogTheme;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null);
        view.setBackgroundResource(R.drawable.rounded_background);
        return view;

    }
}

科特林:

class MyDialogFragment : BottomSheetDialogFragment() {

    override fun getTheme() = R.style.NoBackgroundDialogTheme

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val view: View = View.inflate(requireContext(), R.layout.bottom_sheet_profile, null)
        view.setBackgroundResource(R.drawable.rounded_background)
        return view
    }

}

结果:

在此处输入图像描述

if(view.setBackgroundResource(R.drawable.rounded_background)) 这行dose'nt工作然后尝试设置片段的Xml格式的背景。

于 2021-08-04T21:21:05.393 回答
1

完整的解决方案:

将以下样式属性添加到 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>

然后使用AppBottomSheetDialogTheme从您的代码中创建一个底部工作表对话框。

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

我使用下面的可绘制对象来圆底部工作表背景。

    <?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>

底页 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>
于 2020-11-26T10:11:15.330 回答
1

正如其他答案中所指出的,当状态是BottomSheetBehavior.STATE_EXPANDED角落时,角落会变平。

您可以通过设置peekHeight属性BottomSheetBehavior并使用自定义样式来解决此问题。

abstract class BaseBottomSheetFragment : BottomSheetDialogFragment(){

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    
        if (state == BottomSheetBehavior.STATE_EXPANDED) {
            val displayMetrics = DisplayMetrics()
            requireActivity().windowManager!!.defaultDisplay!!.getMetrics(displayMetrics)
            (dialog as BottomSheetDialog).behavior.peekHeight = displayMetrics.heightPixels
        } else {
            (dialog as BottomSheetDialog).behavior.state = state
        }
    }

    override fun getTheme(): Int {
        return R.style.CustomBottomSheetDialog
    }
}

CustomBottomSheetDialog 样式

<style name="CustomBottomSheetDialog" parent="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/CustomBottomSheet</item>
    <item name="materialButtonStyle">@style/CustomMaterialButtonStyle</item>
</style>

<style name="CustomMaterialButtonStyle" parent="@style/Widget.MaterialComponents.Button">
    <item name="cornerRadius">@dimen/dialog_bottom_radius</item>
</style>

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

<style name="CustomShapeAppearanceBottomSheetDialog" parent="">
    <item name="android:background">@android:color/transparent</item>
    <item name="backgroundTint">@android:color/transparent</item>
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">@dimen/dialog_bottom_radius</item>
    <item name="cornerSizeTopLeft">@dimen/dialog_bottom_radius</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>
</style>
于 2021-09-23T14:33:13.883 回答
0

解决此问题的另一种方法是扩展 BottomSheetDialog 并创建一个适合您需求的自定义类。您可以对布局 xml 文件执行相同操作,并添加背景或任何其他所需的自定义。这还有一个好处,即您在更改背景时将不依赖于 Android (android.support.design.R.id.design_bottom_sheet) 使用的 id 名称(尽管 id 名称的更改很少发生 AFAIK)。

于 2017-12-26T09:05:45.390 回答
0

如果您需要setFitContents=true,我通过 hooking 尝试了解决方案,但是一旦对话框达到状态onStateChanged,它就会从直角闪烁到圆角。EXPANDED这很烦人。

有一种替代解决方法不会导致闪烁,不需要使用私有 API,并且更具可读性(恕我直言)。

查看代码BottomSheetBehavior我们发现:

  /** True if Behavior has a non-null value for the @shapeAppearance attribute */
  private boolean shapeThemingEnabled;

事实证明,如果形状主题被禁用,MaterialShapeDrawable将不会被使用。我们在BottomSheetBehavior.onLayout()

// Only set MaterialShapeDrawable as background if shapeTheming is enabled, otherwise will
// default to android:background declared in styles or layout.
if (shapeThemingEnabled && materialShapeDrawable != null) {
  ViewCompat.setBackground(child, materialShapeDrawable);
}

默认android:background为正是我们所需要的,因为这意味着完全控制背景的渲染方式。

我们可以通过创建单独的样式和设置来禁用材质主题shapeAppearance并将shapeAppearanceOverlay其设为 null:

<style name="Theme.YourApp.NoShapeBottomSheetDialog" parent="Theme.MaterialComponents.BottomSheetDialog">
  <item name="bottomSheetStyle">@style/Theme.YourApp.NoShapeButtonSheet</item>
</style>

<style name="Theme.YourApp.NoShapeButtonSheet" parent="Widget.MaterialComponents.BottomSheet.Modal">
  <item name="shapeAppearance">@null</item>
  <item name="shapeAppearanceOverlay">@null</item>
</style>

扩展BottomSheetDialogFragment和覆盖onCreateDialog

public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
  return new BottomSheetDialog(requireContext(),
                R.style.Theme_Grupin_NoShapeBottomSheetDialog);
}

底部的纸张现在是裸露的,根本没有任何背景。所以我们可以添加任何我们想要的背景,不再触发动画。

于 2021-06-01T21:32:43.963 回答
0

创建一个带有圆角的自定义可绘制对象并将其设置为您的 BottomSheetDialogFragment 布局根的背景

<?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>

然后只需将以下代码添加到您的 BottomSheetDialogFragment 类

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

您甚至可以使用参数来设置边距,如下所示

params.setMargins(50, 0, 50, 0);
于 2018-05-30T14:03:29.927 回答