BottomSheet中的RecyclerView无法正常工作

时间:2019-05-06 21:57:44

标签: android

我在使用bottomsheet行为的布局内部直接遇到RecyclerView的问题。问题在于,当展开底部工作表并向下滚动内容时,当我向上滚动时,它会导致底部工作表开始折叠,而不是先将RecyclerView滚动回到顶部。

这里是video来说明问题。如您所见,当我向下滚动展开的底部工作表时,就会出现问题。它立即开始崩溃,而不是“等待” RecyclerView首先滚动到顶部。

这是我的布局代码

<?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:id="@+id/scheduleRoot"
    android:layout_height="match_parent"
    tools:context=".schedule.ScheduleFragment">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scheduleSheet"
        app:behavior_peekHeight="300dp"
        android:elevation="16dp"
        android:clickable="false"
        android:focusable="false"
        android:background="@drawable/bg_bottom_sheet"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/scheduleRecyclerView"
            android:clickable="true"
            android:focusable="true"
            android:layout_marginTop="8dp"/>

    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

感谢您的帮助!

6 个答案:

答案 0 :(得分:0)

您的实现可能需要更多的编码,而使用提供的代码,我们可能无法为您提供良好的反馈。

尝试此文档 https://material.io/develop/android/components/bottom-sheet-behavior/

另外,我找到了另一个实现。 https://www.youtube.com/watch?v=WeaylHAwIIk

答案 1 :(得分:0)

RecyclerView的滚动行为似乎与BottomSheet的滚动行为发生冲突。

将此添加到xml中的RecyclerView中。

app:layout_behavior="@string/appbar_scrolling_view_behavior"

如果这不起作用,则需要检测RecyclerView的滚动并在RecyclerView滚动时保持BottomSheet展开。

答案 2 :(得分:0)

您的recyclerview项目已超出滚动状态,因此会产生此错误。您提供的布局没有足够的数据来确定原因。您更改的项目是唯一要检查的视图

答案 3 :(得分:0)

我刚刚遇到了同样的问题,但是我通过将其添加到onCreate来解决了这个问题:

androidx.core.view.ViewCompat.setNestedScrollingEnabled(recyclerview, false);

答案 4 :(得分:0)

我遇到了类似的问题:也许我的问题的解决方案会给你一些想法。我的底部工作表已扩展到全高,其中包含回收站视图;底部工作表在用户拖动时折叠,即使回收站视图中的第一项尚不可见。

所以,我做了什么:

  1. 您可以通过 "isDraggable" = true/false 启用/禁用底部工作表拖动
  2. 为回收者视图添加 OnScrollListener。
  3. 覆盖 onScrolled 并检查 layoutManager.findFirstVisibleItemPosition()
  4. 如果第一项可见 - 更新底部工作表行为.isDraggable = true,我还在设置行为之前添加了小延迟。isDraggable = true,因为底部工作表折叠得太快,但您可能不需要它

也许它不是最佳的,但它符合我的需求,也许会对你有所帮助。

答案 5 :(得分:-1)

启用BottomSheet的滚动状态,以便在可见recyclerview 0th项目时进行滚动。

activity_main.xml

<layout 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">

    <data />

    <androidx.coordinatorlayout.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#A8A7A7"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/parent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        android:orientation="vertical"
        app:behavior_hideable="true"
        app:behavior_peekHeight="80dp"
        app:layout_behavior="com.asadmukhtar.recyclerviewinsidebottomsheet.LockableBottomSheetBehavior"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:gravity="center"
            android:text="Drag Me"
            android:textColor="#000"
            android:textSize="20sp"
            android:textStyle="bold" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_items"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

用于处理的LockableBottomSheet文件是否允许拖动选项。

class LockableBottomSheetBehavior<V : View?> : BottomSheetBehavior<V> {
    private var mAllowUserDragging = true

    constructor()

    constructor(context: Context, attrs: AttributeSet?) : super(
        context,
        attrs
    )

    fun setAllowUserDragging(allowUserDragging: Boolean) {
        mAllowUserDragging = allowUserDragging
    }

    override fun onInterceptTouchEvent(
        parent: CoordinatorLayout,
        child: V,
        event: MotionEvent
    ): Boolean {
        return if (!mAllowUserDragging) {
            false
        } else super.onInterceptTouchEvent(parent, child, event)
    }
}

MainActivity.java

var bottomSheetBehavior: LockableBottomSheetBehavior<*>? = null
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding =
        DataBindingUtil.setContentView(this, R.layout.activity_main)

    setUpBottomSheetBehaviour()

    binding.rvItems.layoutManager = LinearLayoutManager(this)
    binding.rvItems.adapter = RecyclerViewAdapter(this)

    binding.rvItems.addOnScrollListener(object : RecyclerView.OnScrollListener() {

        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)

            val firstPosition = (binding.rvItems.layoutManager as LinearLayoutManager)
                .findFirstVisibleItemPosition()

            updateBottomSheetLockState(firstPosition == 0)
        }
    })

}

fun updateBottomSheetLockState(allow: Boolean) {
    bottomSheetBehavior?.setAllowUserDragging(allow)
}


fun updateBottomSheetState(state: Int) {
    if (bottomSheetBehavior != null) {
        bottomSheetBehavior?.state = state
    }
}

private fun setUpBottomSheetBehaviour() {
    val bottomSheetBehavior: BottomSheetBehavior<LinearLayout> =
        BottomSheetBehavior.from(binding.parent)
    this.bottomSheetBehavior = bottomSheetBehavior as LockableBottomSheetBehavior<*>
    updateBottomSheetState(BottomSheetBehavior.STATE_COLLAPSED)
}