【问题标题】:BottomSheetDialog with transparent background具有透明背景的 BottomSheetDialog
【发布时间】:2016-05-08 21:23:29
【问题描述】:

我想显示一个小于屏幕宽度的底部工作表对话框。

例如,Nexus 9 上 Google Play 音乐的分享选项。

你知道如何做到这一点吗?

现在我只是成功地减小了工作表内容的宽度,但背景仍然是屏幕宽度并显示为白色背景。

一些代码:

build.gradle

compile 'com.android.support:design:23.3.0'

主活动

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    mBottomSheetDialog = new BottomSheetDialog(this);
    mBottomSheetDialog.setContentView(R.layout.sheet_test);
    mBottomSheetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialog) {
            mBottomSheetDialog = null;
        }
    });
    mBottomSheetDialog.show();
}

sheet_test

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            style="@style/TextAppearance.AppCompat.Body1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="16dp"
            android:text="Some Text"
            android:textColor="@color/colorPrimary" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#ddd" />

        <TextView
            style="@style/TextAppearance.AppCompat.Body1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="16dp"
            android:text="Some Text" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="#ddd" />

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

【问题讨论】:

  • 请分享一些代码:)
  • 您使用的是什么版本的设计库?你试过最新的(23.3.0)吗?
  • 我认为您只需要使父活动透明即可。参考stackoverflow.com/questions/2176922/…
  • 好的,所以我必须添加一个活动来显示我的底部工作表视图?现在,我从一个显示一些业务信息的活动创建我的 BottomSheetDialog,因此不透明。
  • 您找到解决方案了吗?我也坚持这一点。

标签: android


【解决方案1】:

这对我使用 BottomSheetDialogFragment 时有用:

public class CustomDialogFragment extends BottomSheetDialogFragment {

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

将此添加到您的styles.xml

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

<style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:background">@android:color/transparent</item>
</style>

选项 2:

override fun getTheme() = R.style.CustomBottomSheetDialogTheme

【讨论】:

  • 请注意,setStyle 调用在 onCreateView 方法中不起作用。像上面的例子一样使用时效果很好。感谢您的解决方案!
  • 这必须被选作答案,就像一个魅力!
  • 我尝试了很多解决方案,这是唯一适合我的解决方案,非常感谢:D
  • 这就像一个魅力,它是正确的。在这种情况下,我建议添加一个更新以使用新的 Theme.MaterialComponents: Theme.MaterialComponents.Light.BottomSheetDialog 作为主题。
  • @Mr.Drew Fragment 中的onCreate() 方法在Activity 的onAttachFragment() 之后但在Fragment 的onCreateView() 之前调用。在这种方法中,您可以分配不涉及视图层次结构的变量(即非图形初始化)。 onCreateView()onCreate() 之后被调用,在这里我们附上对话框的视图。对话框本身有一个已经在onCreate() 中创建的框架。因此,只能在 onCreate() 方法中删除该框架。
【解决方案2】:

BottomSheetDialog bottomSheetDialog =new BottomSheetDialog(this,R.style.SheetDialog);

<style name="SheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
    <!--<item name="android:windowCloseOnTouchOutside">false</item>-->
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:colorBackground">     @android:color/transparent</item>
    <item name="android:backgroundDimEnabled">true</item>
    <item name="android:backgroundDimAmount">0.3</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowIsFloating">true</item>
</style>

【讨论】:

  • 能解释几个项目就更好了
  • 这套综合设置有效,但我选择了@Gnzlt的更简单的答案。
  • 答案很有帮助:)
【解决方案3】:

这是设置BottomSheetDialogFragment透明背景最简单的解决方案

它使用以下代码行:

 ((View) contentView.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));

上下文示例:

public class ShareOneTouchAlertNewBottom extends 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(Color.TRANSPARENT);
    }
}

【讨论】:

  • 考虑使用Color.TRANSPARENT而不是getResources().getColor(android.R.color.transparent)
  • 在您的自定义底页中覆盖 setupDialog 方法时,请确保您没有覆盖其中的 onCreateViewsetupDialog 本质上是在这里完成onCreateView 的工作。
【解决方案4】:

抱歉来晚了,如果你成功了,这是你正在寻找的点赞

  @Override    
  public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ((View) getView().getParent()).setBackgroundColor(Color.TRANSPARENT);
}

在创建的活动的底部工作表对话框片段中添加此行。这样就可以了

【讨论】:

  • java.lang.NullPointerException:尝试在 com.maetimes.android.pokekara.section 的空对象引用上调用虚拟方法 'android.view.ViewParent android.view.View.getParent()' .sing.view.TransparentBottomFragment.onActivityCreated(TransparentBottomFragment.java:39) 在 androidx.fragment.app.Fragment.performActivityCreated(Fragment.java:2460)
  • 在应用了大约 10 种解决方案后,这个对我有用。
【解决方案5】:

以下函数覆盖在 BottomSheetDialogFragment 实现中起作用:

class MyTopicBottomSheet : BottomSheetDialogFragment() {


    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

       return super.onCreateDialog(savedInstanceState).apply {
           // window?.setDimAmount(0.2f) // Set dim amount here
           setOnShowListener {
            val bottomSheet = findViewById<View>(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout
            bottomSheet.setBackgroundResource(android.R.color.transparent)
           }
       }
    }

    // Rest of your class here
}

【讨论】:

  • 就像一个魅力。谢谢:)
【解决方案6】:

有点小技巧,但它可以使背景透明。显然你可以用你想要的任何颜色替换“透明”。

mBottomSheetDialog.getWindow().findViewById(R.id.design_bottom_sheet).setBackgroundResource(android.R.color.transparent);

【讨论】:

    【解决方案7】:

    所以,我想出了两个解决方案。

    最好的:

    为您的底部工作表创建一个具有透明背景的活动。 使用协调器布局和底部工作表实现您自己的布局。 设置所需的边距。 设置你想要的内容。

    尚未测试。

    懒人:

    扩展BottomSheetDialogFragment,在onActivityCreated 中添加:

        Resources resources = getResources();
    
        // Set margin for Landscape Mode. Maybe a more elegant solution will be to implements our own bottom sheet with our own margins.
        if (resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            assert getView() != null;
            View parent = (View) getView().getParent();
            CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
            layoutParams.setMargins(
                    resources.getDimensionPixelSize(R.dimen.bottom_sheet_margin_left), // 64dp
                    0,
                    resources.getDimensionPixelSize(R.dimen.bottom_sheet_margin_right), // 64dp
                    0
            );
            parent.setLayoutParams(layoutParams);
        }
    

    【讨论】:

    • 不幸的是,这个工作但不适用于bottomMargin。这样做有什么诀窍吗? @皮埃尔
    【解决方案8】:

    遵循Marco RS 的想法(对我来说,这是唯一可行的解​​决方案),您可以创建一个干净的扩展并应用到对话框中的任何位置。

    扩展名:

    fun BottomSheetDialogFragment.setTransparentBackground() {
    dialog?.apply {
        setOnShowListener {
            val bottomSheet = findViewById<View?>(R.id.design_bottom_sheet)
            bottomSheet?.setBackgroundResource(android.R.color.transparent)
        }
    }
    

    例子:

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setTransparentBackground()
    }
    

    【讨论】:

      【解决方案9】:

      有几种 hackish 方法可以做到这一点。我解决这个问题的方法是推荐的方法。让我们明白为什么?

      在文档中提到

      模态底页。这是 DialogFragment 的一个版本,它使用 BottomSheetDialog 而不是浮动对话框显示底部工作表。

      这意味着应该有一个BottomSheetDialogFragment 使用的方法将默认的Dialog 替换为BottomSheetDialog

      BottomSheetDialogFragment 覆盖的唯一方法是 onCreateDialog()。所以我们将使用这个公共方法来覆盖我们的对话框样式。

      推荐方法

      在扩展BottomSheetDialogFragment overrDide onCreateDialog() 的片段中,这是BottomSheetDialogFragment 本身公开的公共方法。

          override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
              setStyle(STYLE_NO_FRAME, R.style.BottomSheetDialog)
              return super.onCreateDialog(savedInstanceState)
          }
      

      此外,在themes.xml 中覆盖BottomSheetDialog 主题并添加透明背景。

          <style name="BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.BottomSheetDialog">
              <item name="bottomSheetStyle">@style/BottomSheetModal</item>
          </style>
      
          <style name="BottomSheetModal" parent="Widget.Design.BottomSheet.Modal">
              <item name="android:background">@android:color/transparent</item>
          </style>
      

      更多关于:

      • BottomSheetDialogFragment: here
      • onCreateDialog: here
      • 主题BottomSheetDialog:here

      【讨论】:

      • 这是最好的,推荐的和最新的解决方案
      【解决方案10】:

      我有同样的问题,没有任何帮助。 使用此代码解决问题:

        override fun onActivityCreated(savedInstanceState: Bundle?) {
          super.onActivityCreated(savedInstanceState)
          val bottomSheet = (view!!.parent as View)
          bottomSheet.backgroundTintMode = PorterDuff.Mode.CLEAR
          bottomSheet.backgroundTintList = ColorStateList.valueOf(Color.TRANSPARENT)
          bottomSheet.setBackgroundColor(Color.TRANSPARENT)
      }
      

      附: com.google.android.material:material:1.1.0-alpha09

      【讨论】:

      • 这行得通,但我还必须添加 setElevation(0) 以消除阴影。
      【解决方案11】:

      迟到的答案,但我自己遇到了这个问题,并找到了比任何建议更好的解决方案。

      您可以用另一个具有透明背景的布局包裹您的工作表布局并从中添加边距(此处为 16dp):

      <?xml version="1.0" encoding="utf-8"?>
      <FrameLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:background="@color/transparent"
          >
          <android.support.v4.widget.NestedScrollView
              android:layout_width="100dp"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:layout_margin="16dp">
      
              ....
      

      然后像在 Gnzlt answer 中一样为您的工作表添加透明背景:

      <style name="CustomBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
          <item name="bottomSheetStyle">@style/CustomBottomSheetStyle</item>
      </style>
      
      <style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
          <item name="android:background">@android:color/transparent</item>
      </style>
      

      瞧,不需要其他活动。

      【讨论】:

        【解决方案12】:

        这对我有用.. Oncreate Dialog 获取窗口设置颜色

        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Dialog dialog = super.onCreateDialog(savedInstanceState);
            if(dialog.getWindow() !=null){
                dialog.getWindow().setGravity(Gravity.BOTTOM);
                dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
                dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
                dialog.setCancelable(false);
            }
            return dialog;
        }
        

        【讨论】:

        • 这个也适用于BottomSheetDialog,完美
        【解决方案13】:

        这是你的答案:D

        View contentView=LayoutInflater.from(getContext()).inflate(R.layout.bs_add_event,null);
            mBottomSheetDialog.setContentView(contentView);
        
            CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
            params.setMargins(50,50,50,50); // set margin as your wish.
        

        并将android:layout_width="100dp" in nestedScroolView 更改为 android:layout_width="match_parent"

        【讨论】:

          【解决方案14】:

          为您的对话框实例使用“setOnShowListener”,就像在 kotlin 中这样:

                  yourDialogInstance.setOnShowListener {
          
                  //this line transparent your dialog background
                  (dialogView.parent as ViewGroup).background = 
                       ColorDrawable(Color.TRANSPARENT)
          
                  }
          

          kotlin 中的完整代码:

          BottomSheetDialog(this).apply {
          
          val dialogView = LayoutInflater.from(context)
              .inflate(R.layout.your_dialog_layout, null, false)
          
          setContentView(dialogView)
          
          setOnShowListener {
              (dialogView.parent as ViewGroup).background = 
                       ColorDrawable(Color.TRANSPARENT)
          }
          
          show()
          }
          

          【讨论】:

            【解决方案15】:

            BottomSheetDialog 将从您的上下文主题中获取R.attr.bottomSheetDialogTheme 样式,或者使用默认的R.style.Theme_Design_Light_BottomSheetDialog

            BottomSheetDialog的布局xml是R.layout.design_bottom_sheet_dialog。主要内容是一个 id/design_bottom_sheet 样式为?attr/bottomSheetStyle的FrameLayout。

            如果您使用父 Theme.Design.Light.BottomSheetDialog 扩展样式,那么您的所有默认属性(如 colorPrimarycolorAccent)可能会被覆盖。因此,建议在 View Theme 树中使用 ThemeOverlay。您应该像这样从ThemeOverlay.MaterialComponents.Light.BottomSheetDialog 扩展样式:

            <style name="Widget.Test.ButtonSheetDialogTheme" parent="ThemeOverlay.MaterialComponents.Light.BottomSheetDialog">
                <item name="bottomSheetStyle">@style/Widget.Test.BottomSheet.Modal</item>
            </style>
            
            <style name="Widget.Test.BottomSheet.Modal" parent="Widget.MaterialComponents.BottomSheet.Modal">
                <item name="backgroundTint">@android:color/transparent</item>
            </style>
            

            您必须从Widget.MaterialComponents.BottomSheet.Modal 扩展样式,因为默认样式包含这些:

            <style name="Widget.MaterialComponents.BottomSheet" parent="Widget.Design.BottomSheet.Modal">
                <item name="android:background">@null</item>
                <item name="backgroundTint">?attr/colorSurface</item>
                ....
            </style>
            

            BottomSheetDialog 的背景由android:backgroundbackgroundTint 共同决定。但我不确定为什么 backgroundTint 在 android:background 为空时有效。 ???

            更多关于Android Theme的知识:

            【讨论】:

            • 非常感谢,这个答案对我有帮助!
            【解决方案16】:

            我知道这个问题很老,但我仍然回答这个问题并希望它有用。 默认情况下,onCreateView() 方法中指定的布局将被BottomSheetDialogFragment 添加到具有白色背景的FrameLayout 中。因此,您应该在onStart() 方法中将FrameLayout 的背景设置为透明。

            class YourDialog() : BaseBottomDialog() {
               
                override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
                    return inflater.inflate(R.layout.layout_your_dialog, container, false)
                }
                override fun onStart() {
                    super.onStart()
                    (view!!.parent as View).setBackgroundColor(Color.TRANSPARENT)
                }
            }
            

            【讨论】:

              【解决方案17】:

              发现我需要在接受的答案上使用变体,通过更新到 MaterialComponents 以与 AndroidX 兼容以及添加“backgroundTint”作为透明:

              <style name="BottomSheetDialog" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
                  <item name="bottomSheetStyle">@style/BottomSheetDialogStyle</item>
              </style>
              
              <style name="BottomSheetDialogStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
                  <item name="android:background">@android:color/transparent</item>
                  <item name="android:backgroundTint">@android:color/transparent</item>
              </style>
              

              按照原始答案将“BottomSheetDialog”样式应用于片段:

              @Override
              public void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.BottomSheetDialog);
              }
              

              【讨论】:

                【解决方案18】:

                1.首先在您的主题中添加样式:

                   <style name="MyTransparentBottomSheetDialogTheme" parent="Theme.AppCompat.Light">
                       <item name="android:background">@android:color/transparent</item>
                       <item name="android:colorBackground">@android:color/transparent</item>
                   </style>
                

                2。然后用 BottomSheetDialogFragment 附加上面的样式,如下所示:

                   @Override
                   public Dialog onCreateDialog(Bundle savedInstanceState) {
                    return new BottomSheetDialog(getContext(),R.style.MyTransparentBottomSheetDialogTheme);
                   }
                

                【讨论】:

                  【解决方案19】:

                  1 - 以这种方式初始化底部工作表对话框。

                  BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(YourActivity.this, R.style.BottomSheetDialog);
                  

                  2 - 按照 Gnzlt 的建议添加此样式。

                  <style name="BottomSheetDialog" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
                      <item name="bottomSheetStyle">@style/BottomSheetDialogStyle</item>
                  </style>
                  
                  <style name="BottomSheetDialogStyle" parent="Widget.MaterialComponents.BottomSheet.Modal">
                      <item name="android:background">@android:color/transparent</item>
                      <item name="android:backgroundTint">@android:color/transparent</item>
                  </style>
                  

                  【讨论】:

                    【解决方案20】:

                    如果您使用的是 BottomSheetBehavior,请在折叠和展开状态下使用以下代码

                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);             ((View)getParent()).setBackgroundColor(getResources().getColor(<your desire color>));
                    

                    behavior.setState(BottomSheetBehavior.STATE_COLLAPSED); ((View).getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
                    

                    另外,使用

                     behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                                @Override
                                public void onStateChanged(@NonNull View bottomSheet, int newState) {
                                    if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
                                        ((View) mScrollview.getParent()).setBackgroundColor(getResources().getColor(android.R.color.transparent));
                                    }
                                }
                                @Override
                                public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                                    // React to dragging events  
                                }
                            });
                    

                    【讨论】:

                      【解决方案21】:

                      如果您希望所有 BottomSheets 都继承该行为,只需执行以下操作:

                      <style name="Theme.InstaDownloader" parent="Theme.MaterialComponents.Light.NoActionBar">
                             ...
                              <item name="bottomSheetDialogTheme">@style/BottomSheetTheme</item>
                             ...
                       </style>
                      
                       <style name="BottomSheetTheme" parent="Theme.Design.Light.BottomSheetDialog">
                              <item name="bottomSheetStyle">@style/BottomSheetStyle</item>
                       </style>
                      
                       <style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
                              <item name="android:background">@android:color/transparent</item>
                       </style>
                      

                      【讨论】:

                        【解决方案22】:

                        只需在您的 style.xml 中添加以下代码

                        <style name="BottomDialogStyle" parent="Theme.Design.Light.BottomSheetDialog">
                            <item name="android:windowIsFloating">false</item>
                            <item name="android:statusBarColor">@android:color/transparent</item>
                            <item name="android:windowSoftInputMode">adjustResize</item>
                            <item name="bottomSheetStyle">@style/CustomBottomSheetStyle</item>
                        </style>
                        
                        <style name="CustomBottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
                            <item name="android:background">@android:color/transparent</item>
                        </style>
                        

                        另外,更新 onCreate

                         override fun onCreate(savedInstanceState: Bundle?) {
                            super.onCreate(savedInstanceState)
                            setStyle(STYLE_NORMAL, R.style.BottomDialogStyle)
                        }
                        

                        【讨论】:

                          【解决方案23】:

                          对我来说,以下工作:

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

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2018-05-31
                            • 2011-07-13
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多