【问题标题】:Adjust recycler view height when persistent bottom sheet is expanded扩展持久性底页时调整回收站视图高度
【发布时间】:2019-02-15 19:35:39
【问题描述】:

我有一个持久的底部工作表(基本上是一个按钮)和一个回收器视图,它们都包含在 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>

编辑:添加截图

没有底页一切看起来都很好。

随着底部工作表的展开,回收站视图不再完全可见。

编辑 2:添加 GIF

【问题讨论】:

  • its top partly moves out of the screen when the bottom sheet is expanded. 加个 gif 或图片能详细说明一下吗?非常感谢。
  • 你试过删除这个吗?:android:nestedScrollingEnabled="false"
  • 没有变化,只是过度滚动效果消失了。
  • 为什么不让底部的工作表覆盖RecyclerView 的底部?如果您删除 layout_dodgeInsetEdgeslayout_insetEdge,您将拥有您想要的外观,或者,您的实际布局是否比您在此处展示的更复杂?
  • 尝试使用带有 ToolBar 而不是 ActionBar 的 AppBarLayout。还将app:layout_behavior="@string/appbar_scrolling_view_behavior" 添加到您的 RecyclerView。

标签: android user-interface material-design android-coordinatorlayout bottom-sheet


【解决方案1】:

最近遇到了同样的问题,没有找到比删除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){}
})

Java:

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));
    }
});

优点:

  • 屏幕上没有重叠,既不与工具栏也不与底部表按钮;
  • 不会破坏 FAB 的上移功能;
  • RecyclerView 滚动可以与 BottomSheet 一起滑动;

缺点:

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

【讨论】:

  • 这是正确的想法,但公式不完整(如 Cons 中所暗示的),并且填充对 ReyclerView 的滚动条没有影响。考虑到这两个评论,请参阅我的答案以获得修改后的解决方案。
【解决方案2】:

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

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

  • 填充不适用于 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 */ }
})

所引用的LayoutParams的类型要根据自己布局中RecyclerView的parent来改变。

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

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

【讨论】:

    【解决方案3】:

    尝试将此属性放入 RecyclerView:

    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    

    【讨论】:

    • 很遗憾,没有改进。
    【解决方案4】:

    你可以做 2 个解决方案

    1 是设置上边距为RecyclerView

    因为您的 CoordinatorLayout 未在 Toolbar 下方对齐 RecyclerView。所以设置上边距actionBarSize

    android:layout_marginTop="?actionBarSize"
    

    2 如果你想要RecyclerView 出现Toolbar

    android:elevation 设置为RecyclerView,因为Toolbar 具有4dp 高程,并且21 个以上的版本布局是按高程分层的。所以设置

    <android.support.v7.widget.RecyclerView
        ...
        android:elevation="@dimen/design_appbar_elevation"/>
    

    design_appbar_elevation 的值为16dp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-18
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多