วิธีใช้ RecyclerView ภายใน NestedScrollView


210

วิธีการใช้งานRecyclerViewภายในNestedScrollView? RecyclerViewไม่สามารถมองเห็นเนื้อหาหลังจากตั้งค่าอะแดปเตอร์

UPDATEรหัสรูปแบบการปรับปรุง

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="@dimen/keyline_1">

    </RelativeLayout>

    <View
        android:id="@+id/separator"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#e5e5e5" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/conversation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

</android.support.v4.widget.NestedScrollView>


@Mecid ไม่มีเหตุผลที่จะใช้ RecyclerView ภายใน ScrollView (หรือ NestedScrollView)
Gabriele Mariotti

2
@Mecid คุณไม่ควรใส่มุมมองที่เลื่อนได้ในมุมมองเลื่อนอื่นได้ เป็นกฎทั่วไปใน Android
Gabriele Mariotti

6
@GabrieleMariotti ฉันรู้กฎนี้ แต่ NestedScrollView พัฒนาขึ้นเพื่อแก้ไขปัญหานี้
Mecid

1
มันไม่ถูกต้อง NestedScrollView เป็นเหมือน ScrollView แต่รองรับการทำหน้าที่เป็นทั้งผู้ปกครองและเด็กเลื่อนการซ้อน ในกรณีของคุณคุณต้องกำหนดพฤติกรรมการเลื่อนของคุณเอง
Gabriele Mariotti

คำตอบ:


216

แทนที่ recyclerView ของคุณด้วย

<android.support.v7.widget.RecyclerView
    android:id="@+id/conversation"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

ที่นี่

app:layout_behavior="@string/appbar_scrolling_view_behavior"

จะจัดการสิ่งที่เหลือ

อีกอย่างไม่จำเป็นต้องใส่ recyclerView ของคุณเข้าไปใน NestedScrollView


33
ฉันไม่เข้าใจว่าทำไมโซลูชันนี้จึงไม่ได้รับการโหวตมากที่สุด มันไม่ประสบความสำเร็จกับแต่เพียงกับNestedScrollView app:layout_behavior="@string/appbar_scrolling_view_behavior"นี่คือกุญแจ!
hata

3
@RahulUpad นี่มันใช้ได้กับฉัน แต่ฉันคิดว่าบรรทัดสุดท้ายของคุณผิด RecyclerView จะไม่แสดงเลยถ้ามันอยู่ใน NestedScrollView อย่างไรก็ตามคุณเป็นซุปเปอร์สตาร์: D
Leon

3
มันได้ผล! เพิ่งอัปเดตไลบรารี recyclerview คอมไพล์ 'com.android.support:recyclerview-v7:+' '
Fabio Guerra

28
การแก้ปัญหานี้มีวัตถุประสงค์ที่จะนำมาใช้กับCoordinatorLayout, AppBarLayoutและการตั้งค่าที่เหมาะสมlayout_scrollFlagsในมุมมองเด็ก (s) RecyclerViewที่ควรได้รับการเลื่อนด้วย ไม่แน่ใจว่าทำไมถึงถูกตัดออกจากคำตอบ มิฉะนั้นนี่เป็นทางออกที่ดีและเรียบง่าย
Sanvywell

9
ฉันคิดว่ามันสำคัญมากที่จะเข้าใจว่า RecyclerView ของ RECYCLING จะไม่ทำงานที่นี่ ดังนั้นหากคุณมีรายการที่มีความยาวรายการนั้นจะปรากฏขึ้นพร้อมกับการตรึง UI ที่เห็นได้ชัดเจน
Gaket

121

อัพเดท 1

ตั้งแต่ห้องสมุดสนับสนุน Android 23.2.0 มีวิธีการเพิ่มsetAutoMeasureEnabled(true)สำหรับ LayoutManagers มันทำให้ RecyclerView ห่อเนื้อหาและใช้งานได้อย่างมีเสน่ห์
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html

ดังนั้นเพียงเพิ่มสิ่งนี้:

    LayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setAutoMeasureEnabled(true);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setNestedScrollingEnabled(false);


อัพเดท 2

เนื่องจาก 27.1.0 setAutoMeasureEnabledเลิกใช้แล้วดังนั้นคุณควรจัดให้มีการใช้งานแบบกำหนดเองของ LayoutManager ด้วยวิธีการแทนที่isAutoMeasureEnabled()

แต่หลังจากการใช้งานหลายกรณี RecyclerView ฉันขอแนะนำไม่ให้ใช้ในโหมดการปิดผนึกสาเหตุนี้ไม่ใช่สิ่งที่ตั้งใจไว้ พยายามปรับโครงสร้างทั้งหมดของคุณอีกครั้งโดยใช้ RecyclerView ซิงเกิลปกติที่มีหลายรายการ หรือใช้วิธีการกับ LinearLayout ที่ฉันอธิบายด้านล่างเป็นวิธีสุดท้าย


คำตอบเก่า (ไม่แนะนำ)

คุณสามารถใช้ภายในRecyclerView NestedScrollViewก่อนอื่นคุณควรปรับใช้งานของคุณเองLinearLayoutManagerมันทำให้คุณRecyclerViewห่อเนื้อหา ตัวอย่างเช่น:

public class WrappingLinearLayoutManager extends LinearLayoutManager
{

    public WrappingLinearLayoutManager(Context context) {
        super(context);
    }

    private int[] mMeasuredDimension = new int[2];

    @Override
    public boolean canScrollVertically() {
        return false;
    }

    @Override
    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
            int widthSpec, int heightSpec) {
        final int widthMode = View.MeasureSpec.getMode(widthSpec);
        final int heightMode = View.MeasureSpec.getMode(heightSpec);

        final int widthSize = View.MeasureSpec.getSize(widthSpec);
        final int heightSize = View.MeasureSpec.getSize(heightSpec);

        int width = 0;
        int height = 0;
        for (int i = 0; i < getItemCount(); i++) {
            if (getOrientation() == HORIZONTAL) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        heightSpec,
                        mMeasuredDimension);

                width = width + mMeasuredDimension[0];
                if (i == 0) {
                    height = mMeasuredDimension[1];
                }
            } else {
                measureScrapChild(recycler, i,
                        widthSpec,
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);

                height = height + mMeasuredDimension[1];
                if (i == 0) {
                    width = mMeasuredDimension[0];
                }
            }
        }

        switch (widthMode) {
            case View.MeasureSpec.EXACTLY:
                width = widthSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        switch (heightMode) {
            case View.MeasureSpec.EXACTLY:
                height = heightSize;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.UNSPECIFIED:
        }

        setMeasuredDimension(width, height);
    }

    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
            int heightSpec, int[] measuredDimension) {

        View view = recycler.getViewForPosition(position);
        if (view.getVisibility() == View.GONE) {
            measuredDimension[0] = 0;
            measuredDimension[1] = 0;
            return;
        }
        // For adding Item Decor Insets to view
        super.measureChildWithMargins(view, 0, 0);
        RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
        int childWidthSpec = ViewGroup.getChildMeasureSpec(
                widthSpec,
                getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
                p.width);
        int childHeightSpec = ViewGroup.getChildMeasureSpec(
                heightSpec,
                getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
                p.height);
        view.measure(childWidthSpec, childHeightSpec);

        // Get decorated measurements
        measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
        measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
        recycler.recycleView(view);
    }
}

หลังจากนั้นใช้สิ่งนี้LayoutManagerเพื่อคุณRecyclerView

recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));

แต่คุณควรเรียกสองวิธีดังกล่าว:

recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);

นี่setNestedScrollingEnabled(false)ปิดการใช้งานสำหรับการเลื่อนเหตุการณ์จึงไม่ตัดเลื่อนจากRecyclerView NestedScrollViewและsetHasFixedSize(false)ตรวจสอบว่าการเปลี่ยนแปลงในเนื้อหาของอะแดปเตอร์สามารถเปลี่ยนขนาดของRecyclerView

หมายเหตุสำคัญ:โซลูชันนี้มีข้อผิดพลาดเล็กน้อยในบางกรณีและมีปัญหาเกี่ยวกับความสมบูรณ์ดังนั้นหากคุณมีรายการจำนวนมากที่RecyclerViewฉันแนะนำให้ใช้LinearLayoutการปรับใช้มุมมองรายการแบบกำหนดเองให้สร้างอะนาล็อกของอะแดปเตอร์สำหรับมัน ประพฤติตัวเหมือนListViewหรือRecyclerView


19
ข้อควรระวัง! อย่าใช้สิ่งนี้หากคุณมีรายการอยู่ในRecyclerViewนั้นมากมาย
Brais Gabin

1
@BraisGabin คุณพูดถูก: setHasFixedSize (false) ทำให้หลาย ๆ รีเฟรชของ RecyclerView ดังนั้นหากมีหลายรายการมันจะทำงานช้ามาก ในกรณีเหล่านั้นฉันใช้ LinearLayout กับ "อะแดปเตอร์" แบบกำหนดเองเพื่อให้มันทำงานเหมือน ListView หรือ RecyclerView
smbd uknow

1
ขอบคุณมาก! ช่วยฉันชั่วโมง ยังไงก็ตามการตกแต่งไอเท็มสุดท้ายไม่ได้แสดงกับตัวจัดการเลย์เอาต์นี้ (และมีเพียงอันนี้เท่านั้น) บั๊กที่เป็นไปได้
Jjang

2
setAutoMeasureEnabled เลิกใช้แล้วในระดับ API 27.1.0 developer.android.com/reference/android/support/v7/widget/…
Dika

2
แทนที่บูลีน isAutoMeasureEnabled () แทน มันส่งคืนว่าการวัดผ่านของเค้าโครงควรใช้กลไก AutoMeasure ของ RecyclerView หรือถ้ามันควรจะทำโดยการใช้ LayoutManager ของ onMeasure (Recycler, State, int, int) วิธีการนี้จะคืนค่าเท็จโดยค่าเริ่มต้น (จริง ๆ แล้วมันคืนค่าที่ส่งผ่านไปยัง setAutoMeasureEnabled (boolean) ที่คัดค้านแล้ว) และควรถูกแทนที่เพื่อคืนค่าจริงถ้า LayoutManager ต้องการวัดโดยอัตโนมัติโดย RecyclerView หากวิธีการนี้ถูกแทนที่เพื่อส่งกลับจริง, onMeasure (Recycler, State, int, int) ไม่ควรถูกแทนที่
Peterstev Uremgba

100

1) คุณต้องใช้ไลบรารีการสนับสนุน 23.2.0 (หรือ) ด้านบน

2) และความสูงจะเป็นRecyclerViewwrap_content

3) recyclerView.setNestedScrollingEnabled(false)

แต่การทำเช่นนี้รูปแบบการรีไซเคิลไม่ได้ทำงาน (เช่นโหลดทุกมุมมองจะถูกโหลดในครั้งเดียวเพราะwrap_contentต้องการความสูงที่สมบูรณ์RecyclerViewดังนั้นจึงจะดึงเด็กทั้งหมดViews at once. No view will be recycled). Try not to use this pattern unless it is really required. Try to useviewType and add all other views that need to scroll toRecyclerView rather than usingRecyclerView inScrollview` ผลกระทบด้านประสิทธิภาพจะสูงมาก

เพื่อให้ง่าย "มันแค่ทำหน้าที่เหมือนกับLinearLayoutมุมมองลูกทั้งหมด"


6
ขอบคุณ @Ashok การตั้งค่าrecyclerView.setNestedScrollingEnabled(false)ช่วยให้ฉันเลื่อนได้อย่างราบรื่น
Shubhral

3
นี่ควรเป็นคำตอบที่ยอมรับได้! ทำให้มันเป็นอย่างดีชี้ให้เห็นว่าไม่มีมุมมองจะถูกรีไซเคิลและมุมมองทั้งหมดจะถูกดึงในครั้งเดียว
นายอับอาย

3
@AshokVarma ปัญหาเดียวกันฉันกำลังเผชิญอยู่ในขณะนี้ แต่การเลื่อนทำงานได้ดีภายใน recyclerView แต่ฉันไม่สามารถใช้การเลื่อนแบบไม่มีที่สิ้นสุดสำหรับ recyclerview เพราะมุมมองทั้งหมดของ recyclerview ดึงในครั้งเดียวจึงนำไปสู่การเรียกใช้บริการเว็บต่อไป ดังนั้นฉันจะจัดการกับสิ่งนี้ได้อย่างไร
Anantha Babu

@AnanthaBabu แทนที่จะใช้ recyclerview ใน scrollview แปลงรายการทั้งหมดใน scrollview เป็นรายการในมุมมองรีไซเคิล คุณสามารถใช้มุมมองประเภทรีไซเคิลและดูเค้าโครงต่าง ๆ ได้ มีไลบรารี่ที่ดีในการจัดการสิ่งเหล่านี้เช่นกัน (ใช้ไลบรารี่ถ้าคุณมีโครงสร้างมุมมองที่ซับซ้อนและถ้าคุณต้องการส่วนประกอบที่นำมาใช้ซ้ำได้)
Ashok Varma

1
@ShokVarma มีวิธีแก้ไขปัญหาพฤติกรรมรีไซเคิลหรือไม่ ฉันไม่ต้องการให้ recyclerview ดึงเด็กทั้งหมดในคราวเดียว
andro-girl

36

คุณสามารถใช้android:fillViewport="true"เพื่อให้วัดNestedScrollView จะเติมความสูงเหลือ ดังนั้นหากคุณต้องการที่จะเลื่อนคุณสามารถตั้งค่า'sRecyclerViewRecyclerViewNestScrollViewRecyclerViewminHeight


14
หากคุณมีมุมมองรีไซเคิล 200 รายการและคุณทำสิ่งนี้มุมมองซ้อนจะขยายเพื่อเติมเต็มทั้ง 200 รายการ!
RJFares

1
@RJFares ไม่เคยเกิดขึ้น ฉันลองตัวอย่างและใช้ LayoutInspector ตรวจสอบเค้าโครงมันทำงานได้ดี คุณสามารถให้บริการเวอร์ชัน recyclerView ของคุณได้หรือไม่?
zayn

26

เพียงเพิ่มrecyclerView.setNestedScrollingEnabled(false);ก่อนที่setAdapterตัวเองจะทำงานให้ฉัน ฉันไม่ได้เพิ่มapp:layout_behavior="@string/appbar_scrolling_view_behavior"ที่ไหน & ไม่ได้ตั้งค่าเครื่องมือจัดการรูปแบบที่กำหนดเองใด ๆ

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="@color/white"
                android:text="Some Text..."
                android:padding="15dp" />

        </LinearLayout>

        <LinearLayout
            android:orientation="vertical"
            android:padding="15dp"
            android:layout_marginTop="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Quick Links"
                android:textColor="@color/black"
                android:textStyle="bold"
                android:textAllCaps="true"
                android:paddingLeft="20dp"
                android:drawableLeft="@drawable/ic_trending_up_black_24dp"
                android:drawablePadding="10dp"
                android:layout_marginBottom="10dp"
                android:textSize="16sp"/>

            <View
                android:layout_width="fill_parent"
                android:layout_height="1dp"
                android:background="#efefef"/>

            <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/recyclerview"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>

    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

10
แต่ตอนนี้มันไม่รีไซเคิลมุมมองอีกต่อไป?
Mark Buikema

ไม่มันจะรีไซเคิลใช่ไหม
Vignesh Sundar

6
ไม่เลยฉันลองใช้เลย์เอาต์ที่ซับซ้อนมาก ๆ 200 รายการที่ nestedscrollview ขยายขนาดของลูก ๆ ของมันดังนั้นมันจะขยายออกดังนั้นจึงไม่มีการรีไซเคิลที่เกิดขึ้น @MarkBuikema คุณจัดการเพื่อหาทางออกที่ดีกว่าหรือไม่?
RJFares

20

นี่คือสิ่งที่ทำงานให้ฉัน

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>

4
คุณสามารถลบแอปที่สอง: layout_behavior = "@ string / appbar_scrolling_view_behavior"เนื่องจากพฤติกรรมนี้ใช้งานได้เฉพาะกับ CoordinatorLayout direct childs
Pepster

2
นอกจากนี้สิ่งสำคัญคือต้องพูดถึงว่าคุณควรมีเค้าโครงผู้ประสานงานเป็นเค้าโครงรูทของคุณ มันไม่เป็นความจริงเสมอไป
Gaket

10

มีรหัสที่ง่ายและคุณสามารถตรวจสอบการทดสอบได้

<android.support.v4.widget.NestedScrollView
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true"
     app:layout_behavior="@string/appbar_scrolling_view_behavior">
    <android.support.v7.widget.RecyclerView
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
   </android.support.v4.widget.NestedScrollView>

9

เพราะandroidxมันถูกเรียกandroidx.core.widget.NestedScrollView- และมันยังเลื่อนเนยเหมือนกันพร้อมคุณสมบัติisScrollContainerและmeasureAllChildrenเปิดใช้งาน:

<!-- Scrolling Content -->
<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"

    android:isScrollContainer="true"
    android:measureAllChildren="true"

    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fastScrollEnabled="true"
        android:scrollbarStyle="insideInset"
        android:scrollbars="vertical"
        android:splitMotionEvents="false"
        android:verticalScrollbarPosition="right"/>

</androidx.core.widget.NestedScrollView>

7

พยายามที่จะใช้ห้องสมุดนี้ - https://github.com/serso/android-linear-layout-manager

LayoutManager ของไลบรารีทำให้ RecyclerView ล้อมเนื้อหาของมัน ในกรณีนี้ RecyclerView จะ "ใหญ่เท่ากับมุมมองภายใน" ดังนั้นจะไม่มีแถบเลื่อนและผู้ใช้จะใช้ความสามารถในการเลื่อนของ NestedScrollView ดังนั้นจึงจะไม่ชัดเจนเช่น "เลื่อนภายในเลื่อนได้"


1
นี่คือคลาสของ LinearLayoutManager จากไลบรารีนี้: github.com/serso/android-linear-layout-manager/blob/master/lib/…
เข้ารหัสของนินจา

6

นี่คือรหัสที่ฉันใช้เพื่อหลีกเลี่ยงปัญหาการเลื่อน:

mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setHasFixedSize(false);

6

ฉันใช้RecyclerViewภายในNestedScrollViewและมันใช้ได้กับฉัน gotcha เดียวที่ฉันต้องจำไว้คือ NestedScrollView ใช้มุมมองเด็กเพียงคนเดียว ดังนั้นในกรณีของฉันฉันใช้ LienearLayout viewgroup ซึ่งเป็นที่ตั้งของ RecyclerView ของฉันบวกด้วยจำนวนมุมมองอื่น ๆ ที่ฉันต้องการ

ฉันพบปัญหาหนึ่งที่วาง RecyclerView ของฉันไว้ใน NestedScrollView ฉันรู้ว่าการเลื่อนเนื้อหาของ RecyclerView ของฉันหย่อนลง

ฉันรู้ในภายหลังว่า RecyclerView ของฉันได้รับเหตุการณ์การเลื่อนดังนั้นจึงขัดแย้งกับพฤติกรรมการเลื่อนของ NestedScrollView

ดังนั้นเพื่อแก้ปัญหานั้นฉันต้องปิดการใช้งานฟังก์ชั่นการเลื่อนของ RecyclerView ด้วยวิธีนี้ movieListNewRecyclerView.setNestedScrollingEnabled(false);

คุณสามารถเช็คเอาต์ Instagram ของฉันสำหรับวิดีโอสั้น ๆ ของสิ่งที่ฉันทำ นี่คือ instagram ของฉันจัดการ ofelix03

คลิกที่รูปนี้เพื่อดูสิ่งที่ฉันทำ


5

ฉันมี Viewpager และ RecyclerView ภายใน NestedScrollView หลังจากเพิ่มบรรทัดด้านล่าง

recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);

ฉันแก้ไขปัญหาการเลื่อนช้าและการเลื่อนล่าช้า


3
คุณไม่หมายถึงrecyclerView.setHasFixedSize(true);เหรอ
Keno Clayton

3

คุณไม่สามารถใช้มุมมองรีไซเคิลจากภายในมุมมองเลื่อนแบบซ้อน ไม่ได้มีจุดประสงค์เพื่อให้มีมุมมองที่เลื่อนได้เพิ่มเติม แต่เป็นเพราะเป็นลูกของเค้าโครงการเลื่อนที่คุณต้องการมุมมองการเลื่อนแบบซ้อน ฉันมีปัญหาเดียวกัน แต่ในที่สุดฉันก็ย้ายมุมมองข้อความของฉันให้เป็นมุมมองภายใน recyclerview ทำให้ recyclerview เป็นลูกโดยตรงของเค้าโครงผู้ประสานงานและลบมุมมองแบบซ้อน จากนั้นปัญหาทั้งหมดของฉันก็หายไป


8
เนื่องจากRecyclerViewการดำเนินการNestedScrollingChild, ควรจะสามารถที่จะได้รับการเลื่อนผ่านRecyclerView NestedScrollView
Benjamin

ฉันเพิ่งโหวตให้ปฏิเสธstackoverflow.com/review/suggested-edits/9907622ตามความผิดพลาดของภาษาอังกฤษอย่างหมดจด แต่อาจมีเนื้อหาที่มีคุณค่าอยู่ในนั้น - ทุกคนที่ผ่านไปด้วยความรู้ในเรื่องควรดูและดูว่าพวกเขา สามารถทำความสะอาดได้ หากไม่มีสิ่งใดที่เป็นประโยชน์ให้ตั้งค่าสถานะความคิดเห็นของฉันนี้เพื่อลบโดย mods
Mark Amery

3

หากคุณกำลังใช้RecyclerView-23.2.1หรือหลังจากนั้น วิธีแก้ปัญหาต่อไปนี้ใช้ได้ดี:

ในเค้าโครงของคุณให้เพิ่ม RecyclerView ดังนี้:

<android.support.v7.widget.RecyclerView
        android:id="@+id/review_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical" />

และในไฟล์ java ของคุณ:

RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
layoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(new YourListAdapter(getContext()));

ที่นี่layoutManager.setAutoMeasureEnabled(true);จะทำเคล็ดลับ

ลองดูปัญหานี้และบล็อกผู้พัฒนานี้สำหรับข้อมูลเพิ่มเติม


ระวังการใช้ "mRecyclerView.setHasFixedSize (true);" แม้ คุณสามารถใช้งานได้เฉพาะเมื่อคุณไม่ได้เพิ่มหรือลบรายการจากมุมมองของนักรีไซเคิลที่รันไทม์
Gaket

2

ทางออกหนึ่งในการรักษาคุณสมบัติการรีไซเคิลของ recyclerview และหลีกเลี่ยง recyclerview เพื่อโหลดข้อมูลทั้งหมดของคุณคือการกำหนดความสูงของตัวแก้ไขใน recyclerview เอง การทำเช่นนี้ทำให้ recyclerview ถูก จำกัด ให้โหลดได้มากเท่าที่ความสูงสามารถแสดงให้ผู้ใช้เห็นดังนั้นการรีไซเคิลองค์ประกอบของมันหากคุณเลื่อนไปที่ด้านล่าง / ด้านบน


2

มีคำตอบที่ดีมากมาย ที่สำคัญคือคุณต้องตั้งค่าการnestedScrollingEnabled falseดังกล่าวข้างต้นคุณสามารถทำได้ในรหัส java:

mRecyclerView.setNestedScrollingEnabled(false);

แต่คุณมีโอกาสที่จะตั้งค่าคุณสมบัติเดียวกันในรหัส xml ( android:nestedScrollingEnabled="false"):

 <android.support.v7.widget.RecyclerView
 android:id="@+id/recyclerview"
 android:nestedScrollingEnabled="false"
 android:layout_width="match_parent"
 android:layout_height="match_parent" />

2

หากคุณใช้RecyclerView ScrollListenerภายในNestedScrollViewฟัง addOnScrollListener ทำงานไม่ถูกต้องถ้าคุณกำลังใช้ทั้ง

ใช้รหัสนี้

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState); 
              ......
        }
    });

รหัสนี้ปรับการทำงานRecyclerView ScrollListenerภายในNestedScrollView

ขอบคุณ


1

ฉันต้องใช้ CoordinatorLayout พร้อมการเลื่อนแถบเครื่องมือและใช้เวลาตลอดทั้งวันในการทำสิ่งนี้ ฉันได้ทำงานโดยลบ NestedScrollView เลย ดังนั้นฉันแค่ใช้ RelativeLayout ที่รูท

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/rv_nearby"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</RelativeLayout>

1

ห้ามใช้ recyclerView ภายใน NestedScrollView มันอาจทำให้เกิดปัญหาการเรียงซ้อน! ฉันขอแนะนำให้ใช้ ItemViewTypes ใน RecyclerView เพื่อจัดการมุมมองหลายประเภท เพียงเพิ่ม RecyclerView ที่มีความกว้างและความสูงของ match_parent จากนั้นใน recyclerViewAdapter ของคุณจะแทนที่ getItemViewType และใช้ตำแหน่งสำหรับจัดการเค้าโครงที่จะพองตัว หลังจากนั้นคุณสามารถจัดการกับผู้ถือมุมมองของคุณโดยใช้วิธีการ onBindViewHolder


1
nestedScrollView.setNestedScrollingEnabled(true);

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //...
        }
    });


<androidx.core.widget.NestedScrollView
    android:id="@+id/nested"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:layout_below="@id/appBarLayout_orders"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <androidx.constraintlayout.widget.ConstraintLayout ...

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

0

ฉันใช้ส่วนขยายที่ยอดเยี่ยมนี้ (เขียนเป็น kotlin แต่สามารถใช้ได้ใน Java)

https://github.com/Widgetlabs/expedition-nestedscrollview

โดยทั่วไปคุณจะได้รับNestedRecyclerViewภายในแพคเกจใด ๆ ที่ช่วยให้พูดถึงสิ่งที่อยู่ในโครงการของคุณจากนั้นเพียงแค่สร้าง recyclerview ของคุณเช่น

 <com.your_package.utils.NestedRecyclerView
      android:id="@+id/rv_test"
      android:layout_width="match_parent"
      android:layout_height="match_parent" />

ตรวจสอบบทความที่น่าประทับใจนี้โดย Marc Knaup

https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a


0

วิธีการที่จะไม่โหลดเด็กดูทั้งหมดในคราวเดียวภายใน มุมมองเลื่อนซ้อน

Benfits:

  1. ไม่โหลดเด็กทั้งหมดหนึ่งครั้งเมื่อใช้มุมมองเลื่อนซ้อน
  2. คุณสามารถใช้ recycleView.setHasFixedSize (true) เพื่อประสิทธิภาพที่ดีขึ้น
  3. ป้องกันเว็บเซอร์ในการส่งข้อมูลทั้งหมดในครั้งเดียวการแบ่งหน้าใช้งานได้ตามที่คาดไว้
  4. ดีสำหรับชุดข้อมูลจำนวนมากขึ้น
  5. ดีสำหรับอุปกรณ์หน่วยความจำเหลือน้อย
  6. สามารถใช้ประโยชน์จากการเลื่อนแบบซ้อนต่อไป
  7. มีประโยชน์มากเมื่อ recyle ของคุณดูรายการที่ซับซ้อนและต้องการทรัพยากรมากมาย

แก้ไข:

ใน XML ของคุณแทนการใช้match_parentหรือwrap_contentสำหรับ recycleview ใช้ความสูงของการแก้ไข


-5

RecyclerView พร้อม NestedScrollView

    <android.support.v7.widget.RecyclerView
    android:id="@+id/rv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.