【问题标题】:How do I change the default height of a BottomSheetDialog?如何更改 BottomSheetDialog 的默认高度?
【发布时间】:2016-06-08 15:21:37
【问题描述】:

我一直在使用Support Library 23.2 中添加的新BottomSheetDialog,但我想更改对话框的默认高度。我知道这可能与控制初始高度的behavior_peekHeight 属性有关,但是当我无法直接访问BottomSheetBehavior 时,如何在BottomSheetDialog 中设置它?

【问题讨论】:

    标签: android android-support-library android-support-design


    【解决方案1】:

    您可以在 Activity 中设置 bottomSheetDialogTheme,覆盖 bottomSheetStyle 属性的 behavior_peekHeight

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
      <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="behavior_peekHeight">@dimen/custom_peek_height</item>
    </style>
    

    同样的技术也可以用于其他属性,例如将&lt;item name="behavior_hideable"&gt;true&lt;/item&gt; 添加到AppModalStyle 以更改底部工作表是否可隐藏。

    【讨论】:

    • 这在使用 Theme.AppCompat.Light.NoActionBar 作为父布局时不起作用
    • 我注意到behavior_peekHeight只有在值大于208dp时才会生效。这是为什么呢?
    • @AmJay - 应该在版本 23.2.1 中修复。确保更新!
    • 是的 23.2.1 修复了它。谢谢!!
    • 在样式中设置窥视高度不起作用,除非在协调器布局中使用底部工作表对话框。使用 BottomSheetDialogFragment 时设置窥视高度的唯一方法是通过 setUpDialog()。在这里查看答案:stackoverflow.com/a/38873329/6211703
    【解决方案2】:

    你可以在你的代码中使用BottomSheetBehavior

    BottomSheetDialog dialog = new BottomSheetDialog(content);
    .
    .
    .
    dialog.setContentView(view);
    BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
    mBehavior.setPeekHeight(your dialog height)
    dialog.show();
    

    【讨论】:

    • getParent() 给出 null
    【解决方案3】:

    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="behavior_peekHeight">500dp</item>
    </style>
    
    BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.BottomSheetDialog);
                dialog.setContentView(R.layout.layout_bottom_sheet);
                dialog.show();
    

    【讨论】:

    • 这对我不起作用,底部的表格占据了整个屏幕的高度。
    • 改变behavior_peekHeight
    • 显然我做到了。但我放什么值并不重要。
    • 很棒的朋友。它节省了我的 8 小时
    • 出现此错误:无法解析符号“Theme.Design.Light.BottomSheetDialog”
    【解决方案4】:

    适合我

      override fun onStart() {
        super.onStart()
        dialog?.also {
            val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
            bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
            val behavior = BottomSheetBehavior.from<View>(bottomSheet)
            behavior.peekHeight = resources.displayMetrics.heightPixels //replace to whatever you want
            view?.requestLayout()
        }
    }
    

    【讨论】:

    • 它对我有用,只是更改为 WRAP_CONTENT bottomSheet.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
    【解决方案5】:

    老实说,我不知道为什么没有人提到这些简单的方法,但是:

    override fun onResume() {
        super.onResume()
    
        dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
        // or since com.google.android.material:material:1.1.0-beta01
        (dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
    
    }
    //or
    dialog.behavior.peekheight = YOUR_VALUE
    

    直接回答问题

    :如何直接访问 BottomSheetBehavior 高度?

    Adialog.behavior.peekheight

    【讨论】:

    • BottomSheetDialog.behavior 现在是私有的
    • @Aguragorn 我可以看到它是defined public
    【解决方案6】:

    另一种方法是继承 BottomSheetDialogFragment 并控制设置内容视图的方式和时间。向上查看视图树,您可以获得BottomSheetDialog 包装内容视图的行为。这不是一个很好的解决方案,因为它需要更多的布局通道。重要的是,当底部工作表的状态为 STATE_HIDDEN 时,我们必须关闭对话框,否则我们显然违反了库中提供的实现。

    以编程方式设置窥视高度后,内容视图必须调用requestLayout(),这确实是另一个布局通道。

    public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
    
    
        private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
    
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                setStateText(newState);
                if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                    dismiss();
                }
    
            }
    
            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            }
        };
    
    @Override
        public void setupDialog(Dialog dialog, int style) {
            super.setupDialog(dialog, style);
            View contentView = View.inflate(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
            dialog.setContentView(contentView);
            mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
            if (mBottomSheetBehavior != null) {
               mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);    
               mBottomSheetBehavior.setPeekHeight(peekHeight);
               contentView.requestLayout();
            }
    }
    

    【讨论】:

    • 此时,您替换的 BottomSheetDialog 比您仍在使用的要多,应该自己滚动吧?
    • @ianhanniballake 我最初的意图是绕过BottomSheetDialog 内部实例BottomSheetCallback,它只是关闭对话框,并拥有我自己的更多控制权。在这种情况下也可以使用行为实例。
    • 请注意,有一个辅助方法 BottomSheetBehavior.from(View) 可以简化您的逻辑(尽管它会抛出 IllegalArgumentExceptions)
    • @ianhanniballake 在我的情况下,您仍然需要指向具有该行为的视图,否则,from() 方法在找到该行为之前不会遍历树,正如您所说它会抛出国际原子能机构。是的,它整理了代码。谢谢。
    【解决方案7】:

    您可以使用 BottomSheetDialogFragment 并以编程方式进行操作。

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        (dialog as? BottomSheetDialog)?.let {
          it.behavior.peekHeight = PEEK_HEIGHT
        }
        return inflater.inflate(R.layout.bottom_sheet_dialog_fragement, container, false)
      }
    

    【讨论】:

      【解决方案8】:

      如果您使用的是 BottomSheetDialogFragment,请复制并粘贴此代码

      private View bottomSheet;
      
      @Override public void onStart() {
          super.onStart();
          Dialog dialog = getDialog();
          if (dialog != null) {
            bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
              bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
            }
            View view = getView();
            view.post(() -> {
              View parent = (View) view.getParent();
              CoordinatorLayout.LayoutParams params =
                  (CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
              CoordinatorLayout.Behavior behavior = params.getBehavior();
              BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
            bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
      // Here you can play with the height of the bottom sheet like pass height as- [view.getMeasuredHeight()/2]
      
                  ((View) bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
                });
              }
            }
      

      【讨论】:

        【解决方案9】:

        结合 Nick 和 litao 的解决方案,这是我们所做工作的完整版本:

         BottomSheetDialog bottomSheet = new BottomSheetDialog(context);
         View view = View.inflate(context, R.layout.your_action_sheet, null);
         bottomSheet.setContentView(view);
         BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(((View) view.getParent()));
         bottomSheetBehavior.setPeekHeight(1000);
         bottomSheet.show();
        

        【讨论】:

          【解决方案10】:

          这就是我决定问题的方式:

             override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
                  val dialog = BottomSheetDialog(context)
                  val view = View.inflate(context, R.layout.bottom_dialog, null)
          
                  val heightInPixels = 500
                  val params = ViewGroup.LayoutParams(MATCH_PARENT, heightInPixels)
          
                  dialog.setContentView(view, params)
          
                  return dialog
              }
          

          主要部分是方法setContentView(view, params),您可以在其中设置对话框的视图和设置所需高度的布局参数。

          【讨论】:

            【解决方案11】:

            这对我来说可以全屏显示 BottomSheetDialog(STATE_EXPANDED)。我在我的 Activity 中使用它。

            private void showBottomSheetDialog() {
                    View dialogView = LayoutInflater.from(this).inflate(R.layout.your_custom_layout, null);
                    BottomSheetDialog dialog = new BottomSheetDialog(NewWorkoutPlanActivity.this);
                    dialog.setContentView(dialogView);
            
                   
                    FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(R.id.design_bottom_sheet);
                    BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
                    ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
            
                    int windowHeight = getWindowHeight();
                    if (layoutParams != null) {
                        layoutParams.height = windowHeight;
                    }
                    bottomSheet.setLayoutParams(layoutParams);
                    behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            
                    dialog.show();
            
                }
            
                private int getWindowHeight() {
                    // Calculate window height for fullscreen use
                    DisplayMetrics displayMetrics = new DisplayMetrics();
                    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
                    return displayMetrics.heightPixels;
                }
            

            【讨论】:

              【解决方案12】:

              我得到了一个 hack 并使用了它。

              如果您想以编程方式进行。

                  behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                      @Override
                      public void onStateChanged(@NonNull View view, int i) {
                          behavior.setPeekHeight(yourMinHeight);
                      }
              
                      @Override
                      public void onSlide(@NonNull View view, float v) {
              
                      }
                  });
              

              谢谢。

              【讨论】:

                【解决方案13】:

                我们真正想要实现的方法是让 LayoutParams 工作。在扩展对话框的内容视图时,不传递对话框中的parentView Window 将使 rootView 的 xml 配置实际上不起作用。

                所以这里有一个解决方案:

                val contentWidth = ViewGroup.LayoutParams.MATCH_PARENT
                val contentHeight = 500 // px
                dialog.setContentView(view, ViewGroup.LayoutParams(contentWidth, contentHeight))
                

                【讨论】:

                  【解决方案14】:

                  您可以在onStart() 方法中从getBehaviour() 检索BottomSheetBehavior 对象,然后从那里修改窥视高度。

                  @Override
                  protected void onStart() {
                      super.onStart();
                      getBehavior().setPeekHeight(/* Peek Height in px */);
                  }
                  

                  【讨论】:

                  • BottomSheetDialogFragment 中没有 getBehaviour()
                  【解决方案15】:

                  如果您正在扩展 BottomSheetDialogFragment,您可以执行以下操作来获取 BottomSheetBehavior:

                  public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
                      Dialog dialog = super.onCreateDialog(savedInstanceState);
                      //Must add any view here, actual view will be inflated in onCreateView
                      dialog.setContentView(new View(getContext()));
                      //Dialog wraps view in frame layout
                      View root = dialog.findViewById(R.id.design_bottom_sheet);
                      //Now we have access to BottomSheetBehavior
                      BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(root);
                      //Do whatever you need:
                      behavior.setPeekHeight(320, true);
                      behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
                  
                      return dialog;
                  }
                  

                  然后照常覆盖 onCreateView:

                      public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
                      //inflate your bottom sheet layout:
                      View root = inflater.inflate(R.layout.browser_bottom_sheet, container, false);
                      //Do what you need with views:
                      ViewPager viewPager = root.findViewById(R.id.viewpager);
                                    ...........
                  
                      return root;
                  }
                  

                  【讨论】:

                    【解决方案16】:

                    使用此代码设置 DialogFragment 或 BottomSheetDialogFragment 的高度。对话框将根据屏幕高度调整其高度

                      override fun onStart() {
                            super.onStart()
                            val window = dialog?.window
                            val ratio = 1.0
                    
                            if (window != null && activity != null) {
                                val heightDialog = (getScreenHeight(requireActivity()) * 0.9f).toInt()
                                window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, (heightDialog * ratio).toInt())
                                window.setGravity(Gravity.BOTTOM)
                            }
                        }
                    

                    【讨论】:

                      【解决方案17】:

                      我的底部工作表对话框具有回收器视图并且没有要显示的项目,因此它正在缩小,但是假设您想将窥视高度设置为 85%,而不管 Recyclerview 中是否存在项目,请尝试此解决方案。

                      在扩展BottomSheetDialogFragment的类中添加以下代码

                      override fun onStart() {
                          super.onStart()
                          (dialog as BottomSheetDialog).behavior.peekHeight = getBottomSheetDialogDefaultHeight()
                          dialog?.let {
                              val bottomSheet = it.findViewById<View>(R.id.design_bottom_sheet)
                              bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
                          }
                      }
                      
                      private fun getBottomSheetDialogDefaultHeight(): Int {
                          val displayMetrics = DisplayMetrics()
                          (context as Activity?)?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
                          return displayMetrics.heightPixels * 85 / 100
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2016-09-29
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多