nestedscrollview中的RecyclerView的onBindViewHolder一次被所有项目调用

问题描述 投票:4回答:1

我有一个CollapsingToolbar和一个底部导航栏,如图所示:

<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintTop_toTopOf="parent">

        <!-- Scrollable view here -->

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appBar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/height335"
            android:background="@drawable/ic_appbar_bg"
            android:fitsSystemWindows="true"
            app:elevation="0dp">

            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/collapsingToolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                app:contentScrim="@color/colorPrimaryDark"
                app:toolbarId="@+id/toolbar"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="@android:color/transparent"
                    android:contentInsetStart="0dp"
                    android:contentInsetLeft="0dp"
                    android:gravity="center"
                    app:contentInsetEnd="0dp"
                    app:contentInsetEndWithActions="0dp"
                    app:contentInsetLeft="0dp"
                    app:contentInsetRight="0dp"
                    app:contentInsetStart="0dp"
                    app:contentInsetStartWithNavigation="2dp"
                    app:layout_collapseMode="pin"
                    app:theme="@style/ToolbarTheme">

                    <include
                        android:id="@+id/toolbar_header_view"
                        layout="@layout/widget_header_view_top"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        bind:cardDetails="@{viewModel}" />
                </androidx.appcompat.widget.Toolbar>

                <include
                    layout="@layout/widget_header"
                    bind:cardDetails="@{viewModel}" />

            </com.google.android.material.appbar.CollapsingToolbarLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/swipe"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <!-- just a nestedscrollview
            override fun onTouchEvent(ev: MotionEvent): Boolean {
                return scrollable && super.onTouchEvent(ev)
            }

            override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
                return scrollable && super.onInterceptTouchEvent(ev)
            }

            fun setScrollingEnabled(enabled: Boolean) {
                scrollable = enabled
            } -->
            <com.android.utils.LockableNestedScrollView
                android:id="@+id/nestedScrollView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior"
                android:clipChildren="false"
                android:clipToPadding="false"
                android:fillViewport="true">

               <LinearLayout>
                    <Some views...
                    <androidx.fragment.app.FragmentContainerView
                        android:id="@+id/nav_host_fragment"
                        android:layout_width="match_parent"
                        app:layout_behavior="@string/appbar_scrolling_view_behavior"
                        android:layout_height="match_parent" />

                </LinearLayout>

            </com.android.utils.LockableNestedScrollView>

        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="@{()->viewModel.fabClicked()}"
        android:src="@drawable/ic_plus"
        app:fabCustomSize="@dimen/fab70"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        android:elevation="@dimen/elevation3"
        android:paddingTop="@dimen/padding10"
        app:itemTextAppearanceActive="@style/BottomNavigationViewTextStyle"
        app:itemTextAppearanceInactive="@style/BottomNavigationViewTextStyle"
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/nav_view" />

单击导航栏项目时,片段容器将被片段替换。问题是在其中一个片段中,我有一个recyclerview。 recyclerview中所有项目的onBindView一次被全部调用。我需要避免这种情况,主要是因为我试图像这样实现分页:

override fun onBindViewHolder(holder: TopUpViewHolder, position: Int) {
    val item = myDataset[position]
    holder.bind(item)
    if (position == this.itemCount - 1){
        // do your load more task here
        viewModel.fetchTopUpData()
    }
}

((我尝试附加滚动侦听器,并像this那样实现分页。但是即使用户未到达末尾,canScrollVertically(1)也会被调用,这可能是由于nestedscrollview本身。]

这是我的recyclerview片段:

<?xml version="1.0" encoding="utf-8"?>

<data>

    <import type="android.view.View" />

    <variable
        name="viewmodel"
        type="com.android.ui.topup.viewmodel.TopUpViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:padding="@dimen/padding15">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:orientation="vertical">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/status_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingBottom="@dimen/padding20"
            android:visibility="@{viewmodel.headerVisibility}">

            <TextView
                android:id="@+id/recentLabel"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/margin20"
                android:text="@string/recent_top_ups"
                android:textAllCaps="true"
                android:textColor="@color/topup_label_text_color"
                android:textSize="@dimen/text12"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/viewAll"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/margin20"
                android:onClick="@{()->viewmodel.viewAllClicked()}"
                android:text="@string/view_all"
                android:textColor="@color/topup_label_color_orenge"
                android:textSize="@dimen/text14"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        </androidx.constraintlayout.widget.ConstraintLayout>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/topUpRCView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:nestedScrollingEnabled="false"
            android:clipChildren="false"
            android:clipToPadding="false"
            app:scrollListener="@{viewmodel.scrollListener}" />

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:visibility="@{viewmodel.fetchingFlag?View.VISIBLE:View.GONE}" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/empty_list"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="@{viewmodel.listEmpty}"
        android:orientation="vertical">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/ic_illustration_receipt"/>
        <TextView
            android:id="@+id/empty_list_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/you_have_no_topup_requests"
            android:fontFamily="@font/colfaxregular"
            android:textColor="#333547"
            android:layout_marginTop="36dp"
            android:textSize="@dimen/text16"
            android:alpha=".3"/>

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

我尝试过的事情:

  1. 在回收站视图中添加了android:nestedScrollingEnabled="false"
  2. 添加app:layout_behavior="@string/appbar_scrolling_view_behavior"
  3. 将recyclerview的高度更改为match_parent wrap_content,也设置为0,并将布局权重设置为1(RCV在线性布局内)
  4. [https://stackoverflow.com/a/44470106/6341943 =>由于某种原因添加标题查看器]
  5. https://stackoverflow.com/a/37558761/6341943 =>无法执行此操作,因为我有一个bottomnavbar

现在为怪异部分如果我将片段保留在viewpager中,则由于某种原因该问题不会发生。 (即使此hack无法使用,也因为它弄乱了我的collpsingToolbarLayout)

android-fragments android-recyclerview android-viewpager android-collapsingtoolbarlayout android-nestedscrollview
1个回答
0
投票

我已经浪费了至少一个星期的时间,唯一可行的解​​决方案是删除nestedscrollview。要使recyclerview实际为回收视图,请必须删除 nestedscrollview。如果您恰好在里面有多个view,而不仅仅是recyclerview,则必须通过设置不同的观看者,然后将其添加为recyclerview的项,然后添加

app:layout_behavior="@string/appbar_scrolling_view_behavior"

到recyclerview或recyclerview的父级(父级除了Recyclerview之外,没有其他任何视图可以正常工作。

就我而言,要求如下:

  <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        app:layout_constraintTop_toTopOf="parent">

        <!-- Scrollable view here -->

        <com.google.android.material.appbar.AppBarLayout
            ....   >

            <com.google.android.material.appbar.CollapsingToolbarLayout
                ....>

                <androidx.appcompat.widget.Toolbar
                    ....>

                    <include
                        android:id="@+id/toolbar_header_view"
                        .... />
                </androidx.appcompat.widget.Toolbar>

                <include layout="@layout/widget_header" />
            </com.google.android.material.appbar.CollapsingToolbarLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            ....>
            <LinearLayout orientation="vertical" ....>
                <View .../>  <!-- I needed to have these two views along with recyclerview and i wanted them to do nestedscroll along with recyclerview -->
                <View .../>
                <androidx.recyclerview.widget.RecyclerView
                .... />
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

我需要在recyclerview之前有两个视图,我希望它们与recyclerview一起进行嵌套滚动。唯一有效的方法是将其删除到视图中并将其添加为recyclerview的前两项,然后添加

app:layout_behavior="@string/appbar_scrolling_view_behavior"

swipetorefresh布局

希望这对某人有帮助。如果需要,我将添加更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.