CoordinatorLayout中双RecyclerView联动滚动异常问题求助
Hey there! I see the issue you're facing—your first RecyclerView is scrolling independently while the second one stays put, and you want both to scroll in sync along with the AppBarLayout. Let's break down why this is happening and how to fix it.
Why the Current Setup Isn't Working
Right now, your two RecyclerViews sit inside a RelativeLayout with the appbar_scrolling_view_behavior attached. The first RecyclerView uses wrap_content for height, which lets it scroll on its own, while the second uses match_parent but doesn't sync with the first because they're separate scrollable views. They aren't part of a single scrollable container, so their scroll behaviors are completely independent.
Solution 1: Use NestedScrollView as a Single Scroll Container (Recommended)
The simplest and most reliable way to get both RecyclerViews to scroll together is to wrap them (along with their header TextViews) in a NestedScrollView. This turns the entire content area into one scrollable unit that works seamlessly with the CoordinatorLayout and AppBarLayout.
Here's your modified layout code:
<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:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/colorThemeDark" android:fitsSystemWindows="true" android:stateListAnimator="@drawable/appbar_always_elevated" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:collapsedTitleGravity="left" app:contentScrim="@color/colorThemeDark" app:expandedTitleGravity="center|bottom" app:expandedTitleTextAppearance="@style/ExpandedAppBar" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/circleView" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerHorizontal="true" android:layout_gravity="center_vertical|center_horizontal" android:src="@drawable/main_logo" app:layout_collapseMode="none" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <!-- Replace inner RelativeLayout with NestedScrollView --> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:fillViewport="true"> <!-- Use LinearLayout to stack content vertically --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:background="#323642"> <RelativeLayout android:id="@+id/firstText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:paddingLeft="10dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="What you learn today?" android:textColor="@color/colorWhite" android:textStyle="bold" /> </RelativeLayout> <android.support.v7.widget.RecyclerView android:id="@+id/catBoxes" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:paddingLeft="5dp" android:paddingRight="5dp" android:nestedScrollingEnabled="false" /> <!-- Disable internal scrolling --> <RelativeLayout android:id="@+id/secondText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:paddingLeft="10dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Recommended for you" android:textColor="@color/colorWhite" android:textStyle="bold" /> </RelativeLayout> <android.support.v7.widget.RecyclerView android:id="@+id/catMenu" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:nestedScrollingEnabled="false" /> <!-- Disable internal scrolling --> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout>
Key Changes Explained:
- NestedScrollView: Acts as the single scrollable container that syncs with the AppBarLayout.
android:fillViewport="true"ensures it takes up the full screen height. - LinearLayout: Replaces the inner RelativeLayout to stack all content (headers + RecyclerViews) vertically in a continuous flow.
- android:nestedScrollingEnabled="false": Added to both RecyclerViews to disable their internal scrolling behavior—this lets the NestedScrollView handle all scrolling, ensuring both lists move together.
- RecyclerView Height: Changed to
wrap_contentso the NestedScrollView can correctly measure the total height of each list.
Solution 2: Sync Scroll Events Programmatically (Alternative)
If you prefer not to use NestedScrollView, you can manually sync the scroll positions of the two RecyclerViews by adding scroll listeners. Here's how:
In your Activity/Fragment:
RecyclerView catBoxes = findViewById(R.id.catBoxes); RecyclerView catMenu = findViewById(R.id.catMenu); // Sync catMenu with catBoxes scrolling catBoxes.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); catMenu.scrollBy(dx, dy); } }); // Optional: Sync catBoxes with catMenu scrolling if needed catMenu.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); catBoxes.scrollBy(dx, dy); } });
Note: This approach might have minor performance issues or sync lag compared to the NestedScrollView method, so it's better to use Solution 1 unless you have specific reasons to avoid NestedScrollView.
内容的提问来源于stack exchange,提问作者user9779588

