NestedScrollView 内的 RecyclerView:滚动不起作用

问题描述 投票:0回答:0

我里面有

RecyclerView
NestedScrollView
。如果
NestedScrollView
内容(包括传递给
NestedScrollViews
适配器的列表)高于特定高度,我想要的是滚动
RecyclerViews
的全部内容。

我有自定义

NestedScrollView
类来处理这个测量
onMeasure
内所有儿童的身高,如果儿童总身高超过一定值,它应该启用滚动而不是展开
NestedScrollView
高度。 (我需要这个功能,因为
NestedScrollView
被允许扩展到最大显示高度的 40%)。

如果我用包含

NestedScrollView
RelativeLayouts
TextViews
等的通用组件填充
Buttons
,此功能运行良好。但是
RecyclerView
出于某种原因完全阻止了整个
NestedScrollView
的滚动。

这里是从

NestedScrollView:

登录
ScrollViewWithMaxHeight: onMeasure curr_height: 11678, max: 966

嵌套滚动视图:

class ScrollViewWithMaxHeight: NestedScrollView{
    private var maxHeight = WITHOUT_MAX_HEIGHT_VALUE

    constructor(context: Context) : super(context) {}
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
    constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle) {}

    var onHeightChangeListener: ((Int)->Unit)? = null
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        var measuredHeight = heightMeasureSpec
        val currHeight = getCurrContentHeight()
        try {
            val heightSize: Int
            App.log("ScrollViewWithMaxHeight: onMeasure curr_height: $currHeight, max: $maxHeight")
            if (maxHeight != WITHOUT_MAX_HEIGHT_VALUE && currHeight > maxHeight) {
                heightSize = maxHeight
            } else {
                heightSize = currHeight
            }
            measuredHeight = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST)
            layoutParams.height = heightSize
            onHeightChangeListener?.invoke(heightSize)
        } catch (e: Exception) {

        } finally {
            App.log("ScrollViewWithMaxHeight: onMeasure final: $measuredHeight")
            super.onMeasure(widthMeasureSpec, measuredHeight)
        }
    }

    private fun getCurrContentHeight(): Int{
        var height = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            val h = child.measuredHeight
            App.log("ScrollViewWithMaxHeight: getCurrChildHeight: $h")
            if (h > height) height = h
        }

        return height
    }

    fun setOnDynamicHeightChangeListener(l: (Int)->Unit){
        onHeightChangeListener = l
    }

    fun setMaxHeight(maxHeight: Int) {
        this.maxHeight = maxHeight
    }

    companion object {
        var WITHOUT_MAX_HEIGHT_VALUE = -1
    }
}

RecyclerView 初始化 + 布局:

list = findViewById<RecyclerView>(R.id.list).also { rv ->
                rv.isNestedScrollingEnabled = false
                rv.setOnTouchListener { _, _ -> false }
                rv.adapter = adapter
                rv.layoutManager = LinearLayoutManager(a)
            }

布局:

 <RelativeLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            android:clipChildren="false">
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/list"
                android:paddingTop="8dp"
                android:paddingBottom="8dp"
                android:clipToPadding="false"
                android:clipChildren="false"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    
            <components.loading_indicator.LoadingIndicator
                android:id="@+id/progress"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true" />
    
        </RelativeLayout>

嵌套滚动视图初始化:

it.findViewById<ScrollViewWithMaxHeight>(R.id.scrollParent).also { sv->
                sv.setMaxHeight(getScrollViewHeight())
                sv.setOnDynamicHeightChangeListener { h-> }
                sv.isFillViewport = true
                sv.viewTreeObserver.addOnScrollChangedListener {
                    isScrollOnTop = sv.scrollY == 0
                }
            }

这是导致滚动滞后的问题:

2023-03-28 09:48:18.430 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:18.435 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:18.440 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:18.445 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.955 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.962 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.967 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.973 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.979 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.985 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.990 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:27.996 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.002 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.008 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.013 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.019 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.025 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.031 I  RecyclerViewAdapter: onCreateViewHolder: creating item
2023-03-28 09:48:28.037 I  RecyclerViewAdapter: onCreateViewHolder: creating item
...

这是里面的日志

onCreateViewHolder
。它调用列表中的每个项目。即使我尝试滚动,它又被调用了。不确定是什么原因造成的。我的应用程序中到处都是
RecyclerViews
,只有这个没有回收。

好的,我找到了造成这种情况的原因。真的很奇怪。我在

RecyclerView
上方有另一个水平的
NestedScrollView
(这显然不是
NestedScrollView
的一部分,因为它是静态的并且它不应该垂直滚动。它只是带有项目的水平选择器。

一旦我将它从布局中删除,垂直滚动就会像往常一样进行适当的回收。

我的布局设计和组件设计是模块化的,我为父母注入了带有膨胀和

addView
功能的布局,所以我可以在代码中制作独立的组件,这些组件可以注入到任何空布局中。 我从中删除了
NestedScrollView
,因为它没有必要重建错误。即使只有
RecyclerView
作为组件,它也会发生(所以我根本不需要嵌套滚动)。

一旦

horizontal_picker_content
被注入并使用,它就会阻塞
vertical_list_container
的回收,这是我的垂直
RecyclerView
被注入的地方。

所以我重建了我的最终布局在我的

DialogBottomSheet
中的样子所以你可以看到它的结构:

<RelativeLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:orientation="vertical"
        tools:ignore="UselessParent">

        <LinearLayout
            android:id="@+id/topInfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

        </LinearLayout>

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:id="@+id/bottomContentContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            android:clipChildren="false">

            <FrameLayout
                android:id="@+id/bottomSheetContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_insetEdge="bottom"
                app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

                <RelativeLayout
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:clipToPadding="false"
                    android:clipChildren="false"
                    android:background="@color/background_paper"
                    app:layout_insetEdge="bottom"
                    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

                    <RelativeLayout
                        android:id="@+id/peekSwiper"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">

                        <LinearLayout
                            android:id="@+id/dialog_title_block"
                            android:layout_width="match_parent"
                            android:layout_height="20dp"
                            android:orientation="horizontal"
                            android:elevation="0dp"
                            android:translationZ="4dp"
                            android:background="@drawable/bg_bottomsheet_top"/>

                    </RelativeLayout>

                    <LinearLayout
                        android:id="@+id/dialog_bottom_block"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="vertical"
                        android:layout_below="@id/peekSwiper"
                        android:layout_gravity="center_horizontal"
                        android:gravity="center_horizontal">

                        <LinearLayout
                            android:id="@+id/dialog_title_content"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="@color/background_paper"
                            android:orientation="vertical">

                            <RelativeLayout
                                android:id="@+id/horizontal_picker_content"
                                android:orientation="vertical"
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:clipToPadding="false"
                                android:clipChildren="false"
                                android:gravity="center">

                                <androidx.recyclerview.widget.RecyclerView
                                    android:id="@+id/horizontalPickList"
                                    android:layout_width="match_parent"
                                    android:layout_height="wrap_content"
                                    android:orientation="horizontal"
                                    android:scrollbars="horizontal"
                                    android:clipToPadding="false"
                                    android:clipChildren="false"
                                    android:paddingStart="16dp"
                                    android:paddingEnd="16dp"
                                    android:paddingTop="8dp"
                                    android:paddingBottom="8dp"/>

                                <include
                                    layout="@layout/menu_item_separator"
                                    android:id="@+id/separator"
                                    android:layout_width="wrap_content"
                                    android:layout_height="1dp"
                                    android:layout_below="@+id/horizontalPickList"/>

                            </RelativeLayout>

                        </LinearLayout>

                        <LinearLayout
                            android:id="@+id/dialog_content"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:orientation="vertical">
                            
                            <RelativeLayout
                                android:layout_width="match_parent"
                                android:layout_height="wrap_content"
                                android:clipChildren="false"
                                android:clipToPadding="false"
                                android:background="@color/background_paper">

                                <LinearLayout
                                    android:id="@+id/vertical_content_parent"
                                    android:layout_width="match_parent"
                                    android:layout_height="wrap_content"
                                    android:clipToPadding="false"
                                    android:clipChildren="false"
                                    android:orientation="vertical">

                                    <LinearLayout
                                        android:id="@+id/vertical_content_container"
                                        android:layout_width="match_parent"
                                        android:layout_height="wrap_content"
                                        android:clipToPadding="false"
                                        android:clipChildren="false"
                                        android:orientation="vertical">

                                    </LinearLayout>

                                </LinearLayout>

                                <LinearLayout
                                    android:id="@+id/vertical_list_container"
                                    android:layout_width="match_parent"
                                    android:layout_height="wrap_content"
                                    android:layout_below="@id/vertical_content_parent"
                                    android:clipToPadding="false"
                                    android:clipChildren="false"
                                    android:orientation="vertical">

                                </LinearLayout>

                            </RelativeLayout>

                        </LinearLayout>

                    </LinearLayout>

                    <LinearLayout
                        android:id="@+id/buttonLayout"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignBottom="@id/dialog_bottom_block"
                        android:layout_gravity="center_horizontal"
                        android:gravity="center_horizontal"
                        android:layout_centerHorizontal="true"
                        android:orientation="vertical">

                    </LinearLayout>

                </RelativeLayout>

            </FrameLayout>

        </androidx.coordinatorlayout.widget.CoordinatorLayout>

    </RelativeLayout>
android android-recyclerview android-nestedscrollview
© www.soinside.com 2019 - 2024. All rights reserved.