展开持久性底部工作表时调整回收器视图高度

Hen*_*ste 9 user-interface android material-design android-coordinatorlayout bottom-sheet

我有一个持久的底部工作表(基本上是一个按钮)和一个回收器视图,它们都包含在 CoordinatorLayout 中。

当底部工作表展开时,我不希望它遮挡回收站视图。我可以通过分别app:layout_insetEdge="bottom"在底部工作表和app:layout_dodgeInsetEdges="bottom"回收站视图中进行设置来实现这一点。

但是,由于回收器视图的高度设置为android:layout_height="match_parent",当底部工作表展开时,它的顶部部分移出屏幕。

相反,我希望回收器视图根据底部工作表的高度动态调整其高度,使其不再移出屏幕。我怎样才能做到这一点?

这是完整的布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:nestedScrollingEnabled="false"
    app:layout_dodgeInsetEdges="bottom" />

<Button
    android:id="@+id/bottom_sheet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/update_all"
    android:foreground="?attr/selectableItemBackground"
    android:background="@drawable/angled_button"
    app:behavior_hideable="false"
    app:behavior_peekHeight="0dp"
    app:layout_insetEdge="bottom"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />

</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

编辑:添加了截图

没有底片,一切看起来都很好。 在此处输入图片说明

随着底部工作表展开,回收站视图不再完全可见。 在此处输入图片说明

编辑 2:添加了 GIF

在此处输入图片说明

Nik*_*kin 9

最近面临同样的问题,没有找到比删除app:layout_dodgeInsetEdges="bottom"和使用填充更好的方法。这是如何实现的:

科特林:

val rv = findViewById<RecyclerView>(R.id.recycler_view))
val behavior = BottomSheetBehavior.from(findViewById<Button>(R.id.bottom_sheet))
behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback(){
    override fun onSlide(bottomSheet: View, offset: Float) {
        rv.setPadding(0, 0, 0, (bottomSheet.height * offset).toInt())
    }

    override fun onStateChanged(bottomSheet: View, newState: Int){}
})
Run Code Online (Sandbox Code Playgroud)

爪哇:

RecyclerView rv = (RecyclerView) findViewById(R.id.recycler_view); 
BottomSheetBehavior behavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet));
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
    @Override
    public void onStateChanged(@NonNull View bottomSheet, int newState) {
    }

    @Override
    public void onSlide(@NonNull View bottomSheet, float slideOffset) {
        rv.setPadding(0, 0, 0, (int)(slidingView.getHeight() * offset));
    }
});
Run Code Online (Sandbox Code Playgroud)

优点:

  • 屏幕上没有重叠,工具栏和BottomSheet按钮都没有;
  • 不会破坏 FAB 的上移功能;
  • RecyclerView 滚动可以随着BottomSheet 的向上滑动而完成;

缺点:

  • 不是纯 XML,需要编码;
  • 需要额外的更改以保持原始填充(但仍然可能且相对容易做到)


Ron*_*nan 6

尼基塔接受的答案有正确的想法,但有两个问题:

  • 建议的填充公式仅在底部工作表完全展开时才正确,因为作为 onSlide 回调参数提供的 slipOffset 与底部工作表的窥视高度和完整高度之间的差值成正比,而不仅仅是与其完整高度成正比

  • 填充不适用于 recyclerview 的快速滚动条,该滚动条会继续延伸到底部工作表下方。另一方面,保证金则按预期运行。

下面是考虑了这两个修正的 Kotlin 实现:

val behavior = BottomSheetBehavior.from(constraintLayout)
behavior.setBottomSheetCallback(object : BottomSheetCallback() {

    override fun onSlide(bottomSheet: View, slideOffset: Float) {
        val margin = behavior.peekHeight + (bottomSheet.height - behavior.peekHeight) * slideOffset
        recyclerview.updateLayoutParams<FrameLayout.LayoutParams> { bottomMargin = margin.toInt() }
    }

    override fun onStateChanged(bottomSheet: View, newState: Int) { /* Nothing to do */ }
})
Run Code Online (Sandbox Code Playgroud)

引用的 LayoutParams 类型应根据您自己布局中的 RecyclerView 的父级进行更改。

请注意,RecyclerView 的底部边距应设置为布局 xml 中底部工作表的窥视高度,以便在活动加载时、发生任何滑动之前获得正确的布局。

上面的示例适用于不可隐藏的底部工作表,这意味着 slipOffset 参数只能从 0 到 1。对于可隐藏的底部工作表,当 SlideOffset 介于 -1 和 0 之间时,应使用另一个公式:behavior.peekHeight * (1 + slideOffset)