ActionBar下面的Persistent BottomSheet

时间:2017-02-27 16:56:24

标签: android android-layout android-actionbar bottom-sheet

我的应用布局包含自定义toolbar和持久性BottomSheet - 都位于CoordinatorLayout内。

点击按钮我想显示BottomSheet。现在,工作表全屏显示并覆盖toolbar。通过将应用主题设置为Theme.AppCompat.Light.DarkActionBar BottomSheet保持在ActionBar以下,但该栏无法自定义。

有没有办法将持久性BottomSheet的高度限制为全屏 - ActionBar高度?

这是我在activity_main.xml

中的代码
<android.support.design.widget.CoordinatorLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:attrs="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.test.MainActivity">

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

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        app:elevation="20dp"
        android:elevation="20dp"
        android:layout_height="?attr/actionBarSize">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            app:elevation="20dp"
            android:elevation="20dp"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>
    </android.support.design.widget.AppBarLayout>
    </LinearLayout>
    <include layout="@layout/bottom_sheet_additem"/>
</CoordinatorLayout>

以下是sheet_bottom.xml

的代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottomSheetLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    app:behavior_hideable="true"
    app:behavior_peekHeight="0dp"
    android:fitsSystemWindows="true"
    app:layout_behavior="@string/bottom_sheet_behavior">

    <TextView
        android:id="@+id/bottomsheet_text"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="Lorem Ipsum Dolor..."
        android:textColor="#FFFFFF" />
</RelativeLayout>

Screenshot 左侧的图像显示BottomSheet停在Toolbar下方 - 这与我当前的代码不兼容。目前它看起来像右边的图片。

5 个答案:

答案 0 :(得分:15)

我遇到了同样的问题。

尝试将您的包含在activity_main.xml中的另一个CoordinatorLayout中,并使用marginTop:

<android.support.design.widget.CoordinatorLayout
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:attrs="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.test.MainActivity">

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

        <android.support.design.widget.AppBarLayout
          android:layout_width="match_parent"
          app:elevation="20dp"
          android:elevation="20dp"
          android:layout_height="?attr/actionBarSize">

          <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            app:elevation="20dp"
            android:elevation="20dp"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>
        </android.support.design.widget.AppBarLayout>
    </LinearLayout>

    <android.support.design.widget.CoordinatorLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_marginTop="56dp">

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

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

</CoordinatorLayout>

让我知道它是否适合你。

答案 1 :(得分:1)

我们可以使用app:layout_behavior而不是固定高度

<android.support.design.widget.CoordinatorLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

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

答案 2 :(得分:1)

当您将底页扩展到全屏时,可接受的答案有效,但是在折叠时,它会添加额外的边距,从而使部分折叠布局隐藏在屏幕下方,因此我决定通过编程来设置边距,方法是听变为BottomSheet的折叠/隐藏状态。

首先在xml中的BottomSheet中添加CoordintorLayout

并在回调监听器下方添加。

mBottomSheetBehavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
    @Override
    public void onStateChanged(@NonNull View bottomSheet, int newState) {

        CoordinatorLayout bottomSheet = findViewById(..); // inflate the bottom sheet
        CoordinatorLayout.LayoutParams  layoutParams = 
             (CoordinatorLayout.LayoutParams) bottomSheet.getLayoutParams();

        if (newState == BottomSheetBehavior.STATE_COLLAPSED) 
            layoutParams.setMargins(0, 0, 0, 0); // remove top margin
         else if (newState == BottomSheetBehavior.STATE_EXPANDED) {
            layoutParams.setMargins(0, 100, 0, 0); // add top margin
        
        bottomSheet.setLayoutParams(layoutParams);
    }

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

    }
});

答案 3 :(得分:0)

您的sheet_bottom应该看起来像这样

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main">

 <RelativeLayout
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:behavior_hideable="true"
    app:behavior_peekHeight="?android:attr/actionBarSize"
    app:elevation="@dimen/size_5dp"
    app:layout_behavior="@string/bottom_sheet_behavior">
 </RelativeLayout>

 </androidx.coordinatorlayout.widget.CoordinatorLayout>

答案 4 :(得分:0)

+1 用于以编程方式更新边距。虽然可以通过增加查看高度来抵消 BottomSheet 的隐藏部分,但仅使用上面的原始解决方案意味着边距会投射到底层 UI 元素上,因此滚动操作区域会从实际的 BottomSheet 投射到其他 UI 上。

在BottomSheetCallback 中使用onStateChanged 方法意味着对BottomSheet 已经展开或折叠的事件进行操作。在此阶段添加或删除边距可能会导致看到“抖动”行为,例如,在以编程方式应用边距以将 UI 组件向下移动导致“闪烁”之前,工作表会暂时达到覆盖应用栏的完全展开状态这适用。

相反,我使用 onSlide 方法来检测 BottomSheet 何时向上或向下滑动,并仅在纸张过渡到一半时添加或删除边距。如果在滑动动作中过早地应用了边距,那么用户可以在启动动作后不久再次看到BottomSheet UI 向上或向下跳跃(如果他们已经完成了“fling”,他们不太可能在中途注意到这一点) ' 向上或向下运动。

我还发现获取 AppBar 和状态栏的高度并使用它们来设置所需的填充值以在展开模式下准确放置效果最好。

通过使用小部件以编程方式触发 BottomSheet 状态更改,可以完全避免此挑战。

@Override
        public void onSlide(View bottomSheet, float slideOffset) {
            boolean inRangeExpanding = oldOffSet < slideOffset;
            boolean inRangeCollapsing = oldOffSet > slideOffset;
            oldOffSet = slideOffset;
            if (inRangeCollapsing && slideOffset < 0.5f) {
                //reset padding on top of bottomsheet so there is no padding/overlap onto underlying sheet (which overlaps underlying sheet and so interfers with scrolling behaviour
                bSheetView.setPadding(0,10,0,0);
                Log.d(TAG,"onSlide STATE_COLLAPSING");
            } else if(inRangeExpanding && slideOffset > 0.5f){
                //reset padding on top of bottomsheet so there is padding/overlap onto underlying sheet so it does not write over the top of the menu appbar
                bSheetView.setPadding(0, topMargin,0,0);
                Log.d(TAG,"onSlide STATE_EXPANDING");
            }
        }