ActionBar 下方的持久性 BottomSheet
Persistent BottomSheet below ActionBar
我有一个带有自定义 toolbar
和持久 BottomSheet
的应用程序布局 - 都在 CoordinatorLayout
.
中
点击按钮我想显示 BottomSheet
。现在 sheet 全屏显示并覆盖 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>
左侧的图像显示 BottomSheet
停在 Toolbar
下方 - 这不适用于我当前的代码。目前看起来像右图。
我遇到了同样的问题...我不知道这是否是最好的解决方案,但就目前而言,对我有用。
尝试将您的 include 放入 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>
希望对您有所帮助。
我们可以使用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>
你的 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>
接受的答案在您将底部 sheet 展开到全屏时有效,但在折叠它时,它会增加额外的边距,使折叠布局的一部分隐藏在屏幕下方,所以我决定通过监听 BottomSheet
.
的 collapse/hidden 状态以编程方式放置边距
首先在xml
中的CoordintorLayout
内添加BottomSheet
并在下面添加回调监听器。
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) {
}
});
+1 用于以编程方式更新边距。虽然 BottomSheet 的隐藏部分可以通过增加 peek 高度来抵消,但仅使用上面的原始解决方案意味着边距投影到底层 UI 元素上,因此滚动操作区域从实际 BottomSheet 投影到另一个 UI.
在BottomSheetCallback 中使用onStateChanged 方法意味着对BottomSheet 已经展开或折叠的事件进行操作。在此阶段添加或删除边距可能会导致看到 'jerky' 行为,例如 sheet 在以编程方式应用边距以移动 [=26= 之前暂时达到覆盖应用栏的完全展开状态] 组件下降导致 'flash' 因为这适用。
相反,我使用 onSlide 方法检测 BottomSheet 何时向上或向下滑动,并仅在 sheet 过渡到一半时才添加或删除边距。如果在幻灯片运动中过早应用边距,则用户可以再次看到 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");
}
}
我有一个带有自定义 toolbar
和持久 BottomSheet
的应用程序布局 - 都在 CoordinatorLayout
.
点击按钮我想显示 BottomSheet
。现在 sheet 全屏显示并覆盖 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>
BottomSheet
停在 Toolbar
下方 - 这不适用于我当前的代码。目前看起来像右图。
我遇到了同样的问题...我不知道这是否是最好的解决方案,但就目前而言,对我有用。
尝试将您的 include 放入 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>
希望对您有所帮助。
我们可以使用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>
你的 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>
接受的答案在您将底部 sheet 展开到全屏时有效,但在折叠它时,它会增加额外的边距,使折叠布局的一部分隐藏在屏幕下方,所以我决定通过监听 BottomSheet
.
首先在xml
中的CoordintorLayout
内添加BottomSheet
并在下面添加回调监听器。
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) {
}
});
+1 用于以编程方式更新边距。虽然 BottomSheet 的隐藏部分可以通过增加 peek 高度来抵消,但仅使用上面的原始解决方案意味着边距投影到底层 UI 元素上,因此滚动操作区域从实际 BottomSheet 投影到另一个 UI.
在BottomSheetCallback 中使用onStateChanged 方法意味着对BottomSheet 已经展开或折叠的事件进行操作。在此阶段添加或删除边距可能会导致看到 'jerky' 行为,例如 sheet 在以编程方式应用边距以移动 [=26= 之前暂时达到覆盖应用栏的完全展开状态] 组件下降导致 'flash' 因为这适用。
相反,我使用 onSlide 方法检测 BottomSheet 何时向上或向下滑动,并仅在 sheet 过渡到一半时才添加或删除边距。如果在幻灯片运动中过早应用边距,则用户可以再次看到 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");
}
}