【问题标题】:Bottom Sheet landscape issue底页横向问题
【发布时间】:2017-01-11 13:04:26
【问题描述】:

在横向模式下显示底部工作表对话框时出现错误行为。该问题出现在 24.+ 版本的设计库中。 根据下图,底页仅在横向中未正确显示。我正在使用 BottomSheetDialog 类,我正在关注本教程:http://www.skholingua.com/blog/bottom-sheet-android,在我发布的应用程序中也会出现问题。

我测试了25.+版本,问题没有解决。

横向 24、25.+ 库中的错误

23.+ 库中的相同示例

主要活动

public class MainActivity extends AppCompatActivity {
CoordinatorLayout coordinatorLayout;
private BottomSheetBehavior<View> mBottomSheetBehavior;
private TextView textView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    coordinatorLayout = (CoordinatorLayout) findViewById(R.id.main_content);
    textView = (TextView) findViewById(R.id.textView);
    View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);

    //For your bottom sheet to be displayable, you need to create a BottomSheetBehavior.
    //This is created by getting a reference to the container view and calling BottomSheetBehavior.from() on that container.
    mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);

    mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            switch (newState) {
                case BottomSheetBehavior.STATE_DRAGGING:
                    break;
                case BottomSheetBehavior.STATE_COLLAPSED:
                    mBottomSheetBehavior.setPeekHeight(0);
                    break;
                case BottomSheetBehavior.STATE_EXPANDED:
                    break;
                case BottomSheetBehavior.STATE_HIDDEN:
                    break;
                case BottomSheetBehavior.STATE_SETTLING:
                    break;
            }
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
        }
    });

}


public void onClick(View v) {
    switch (v.getId()) {
        case R.id.button1:
            /**
             * For persistent bottom sheet to work, your layout should contain a coordinator layout,
             * and then in any child view of your coordinator layout, you can make it as a persistent bottom sheet
             * by adding a custom property app:layout_behavior and use behavior_peekHeight to define how much
             * of the Bottom Sheet you want visible.
             */
            textView.setText(R.string.dynamic_persistent_txt);
            mBottomSheetBehavior.setPeekHeight(300);
            mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            break;
        case R.id.button2:
            /**
             * You can also display a Dialog in place of a View in the bottom sheet.
             * To do this, get the view from getLayoutInflater and pass it setContentView of the Dialog.
             */
            View view = getLayoutInflater().inflate(R.layout.bottom_sheet_layout, null);
            TextView textView = (TextView) view.findViewById(R.id.textView);
            textView.setText(R.string.dialog_modal_txt);
            BottomSheetDialog dialog = new BottomSheetDialog(this);
            dialog.setContentView(view);
            dialog.show();
            break;
        case R.id.button3:
            /**
             * You can also display a Fragment in place of a View in the bottom sheet.
             * To do this, you class that extends BottomSheetDialogFragment.
             */
            BottomSheetDialogFragment bottomSheetDialogFragment = new BottomSheetDialogFragmentExample();
            bottomSheetDialogFragment.show(getSupportFragmentManager(), bottomSheetDialogFragment.getTag());
            break;
    }
}

activity_main.xml

<android.support.design.widget.CoordinatorLayout     xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingTop="24dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Dynamic BottomSheet" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="BottomSheetDialog" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="BottomSheetDialogFragment" />
</LinearLayout>

<LinearLayout
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="4dp"
    android:minHeight="120dp"
    android:orientation="vertical"
    android:padding="@dimen/activity_vertical_margin"
    app:behavior_peekHeight="120dp"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior">

    <include layout="@layout/bottom_sheet_layout" />

</LinearLayout>

</android.support.design.widget.CoordinatorLayout>

bottom_sheet_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/CreamyGreen"
android:orientation="vertical">


<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/static_persistent_txt"
    android:padding="16dp"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:textColor="@android:color/white" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:text="@string/ipsum"
    android:textColor="@android:color/white"
    android:textSize="16sp" />
</LinearLayout>

【问题讨论】:

  • 尽管我同意它看起来不对并且感觉很愚蠢,但我认为这是故意的。 AUTO 高度设置强制底页不超出 16:9 比例关键线......这在横向看起来很愚蠢......
  • 我在 Android 问题跟踪器上打开了一个问题,并收到了解决该问题的可能方法,请参阅:code.google.com/p/android/issues/detail?id=231964#c6

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


【解决方案1】:

这可以在 2 行中实现(Kotlin 版本)

class MyBottomSheetFragment : BottomSheetDialogFragment() {
    //....
    override fun onStart() {
        super.onStart()
        //this forces the sheet to appear at max height even on landscape
        val behavior = BottomSheetBehavior.from(requireView().parent as View)
        behavior.state = BottomSheetBehavior.STATE_EXPANDED
    }
}

【讨论】:

  • 像魅力一样工作。谢谢
  • 谢谢!这为我节省了很多工作!
【解决方案2】:

Google 人员按预期关闭了此功能,这是一种解决方法

屏幕高度比有一个神奇的常数,好像做min(actualwidth, themewidth),显然效果不好 使用手机景观,因此将其覆盖为更大的东西

<style name="Theme.Main.Reader">
     ...
     <item name="bottomSheetDialogTheme">@style/ReaderBottomSheelDialog</item>
</style>
<style name="ReaderBottomSheelDialog" parent="Theme.Design.BottomSheetDialog">
     <item name="bottomSheetStyle">@style/BottomSheetStyle</item>
</style>

<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="behavior_peekHeight">512dp</item>
</style>

【讨论】:

  • 谢谢,效果很好。我只需要使用Theme.Design.Light.BottomSheetDialog 来匹配我的应用主题。
  • 这个解决方案有个副作用——屏幕旋转后ActionBar中的字幕消失了。
【解决方案3】:

这是一种解决方法。 (注意:此代码在一个活动中)

View sheetView;//class level variable

private void setUpBottomSheetDialog() {

    bottomSheetDialog = new BottomSheetDialog(this);

    LayoutInflater inflater = LayoutInflater.from(this);
     sheetView = inflater.inflate(R.layout.bottom_sheet_image_source, (ViewGroup) this.getWindow().getDecorView().getRootView(), false);

    bottomSheetDialog.setContentView(sheetView);

    BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) sheetView.getParent());

    bottomSheetDialog.setOnShowListener(dialogInterface -> {
        mBehavior.setPeekHeight(sheetView.getHeight());//get the height dynamically
    });
}

【讨论】:

    【解决方案4】:

    我个人解决这个问题的选择是,在onCreateView之后,你已经有了BottomSheetDialogFragment的主视图

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mainLayout = inflater.inflate(R.layout.fragment_auction_bottom_sheet_dialog, container, false);
        return mainLayout;
    }
    

    并且 onStart 将在您创建视图后执行,因此您可以播放行为:

    @Override
    public void onStart() {
        super.onStart();
        //this expands the bottom sheet even after a config change
        bottomSheetBehavior = BottomSheetBehavior.from((View) mainLayout.getParent());
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }
    

    那么您将始终展开底部工作表

    【讨论】:

    • 这行得通,但它也可以在所有情况下全屏显示。我怎样才能让它以不同的方式工作?例如,我注意到在横向和纵向的情况下共享底页不同。在纵向上它占据屏幕的一部分,而在横向上它占据整个屏幕。我不知道具体是什么逻辑。可能不仅仅是横向检查,因为它也发生在分屏中(占用整个空间)。
    【解决方案5】:

    要让 BottomSheetDialogFragment 始终完全展开(也在横向模式下)打开,我执行以下操作。

    在 onCreateDialog 中,您创建 BottomSheetDialog 和您的视图。将此视图添加到 BottomSheetDialog 后,您可以通过在 BottomSheetBehavior.from() 中使用视图的父级来获取 BottomSheetBehavior。

    然后在 BottomSheetDialogFragment 的 onStart 中调用带有 STATE_EXPANDED 的 BottomSheetBehavior.setState。

    BottomSheetBehavior mBottomBehavior;
    
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        BottomSheetDialog dialog = new BottomSheetDialog(getContext());
        mBinding = SomeBinding.inflate(LayoutInflater.from(getContext()));
        dialog.setContentView(mBinding.getRoot());
        mBottomBehavior = BottomSheetBehavior.from((View) mBinding.getRoot().getParent());
        return dialog;
    }
    
    public void onStart() {
        super.onStart();
        mBottomBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }
    

    我希望这对某人有所帮助。

    【讨论】:

      【解决方案6】:

      BottomSheetDialog 对话框; BottomSheetBehavior bottomSheetBehavior;

      private void createBottomSheet() {
          if (dialog == null){
              dialog = new BottomSheetDialog(this);
      
              final View view = LayoutInflater.from(this).inflate(R.layout.setting_dialog,
                      (ViewGroup)this.getWindow().getDecorView().getRootView(),false);
      
              dialog.setContentView(view);
              bottomSheetBehavior = BottomSheetBehavior.from((View)view.getParent());
              dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                  @Override
                  public void onShow(DialogInterface dialog) {
                      bottomSheetBehavior.setPeekHeight(view.getHeight());
                  }
              });
          }
      }
      

      【讨论】:

        【解决方案7】:

        在androidX中,bottom sheet可以展开如下:

         BottomSheetDialog bottomSheetDialog = 
               new BottomSheetDialog(requireContext());
        
          bottomSheetDialog.setContentView(view);
        
            bottomSheetDialog.show();
        
            FrameLayout bottomSheet = (FrameLayout)
                    bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheeet);
            BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
            behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            behavior.setPeekHeight(0);
        

        如果出现以下错误,这也将很有帮助,同时获得底部工作表行为: “视图不是 coordinatorlayout 的子视图”

        【讨论】:

          【解决方案8】:

          将此函数添加到扩展BottomSheetDialogFragment 的类的实现中会做必要的事情:

          @Override
          public void onStart() {
              super.onStart();
              BottomSheetBehavior.from((View) requireView().getParent()).setState(BottomSheetBehavior.STATE_EXPANDED);
              //  Opens the bottom sheet in expanded state even in landscape mode
              BottomSheetBehavior.from((View) requireView().getParent()).setSkipCollapsed(true);
              //  Skips the peek view of the bottom sheet
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-11-04
            • 2020-05-03
            • 2013-02-23
            • 1970-01-01
            • 2023-03-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多