web-dev-qa-db-ja.com

NestedScrollView内でRecyclerViewを使用する方法?

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>
174
Mecid

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"

残りのものを管理します。

もう1つのこと、あなたのrecyclerViewをNestedScrollViewの中に入れる必要がないこと

182
Rahul Upadhyay

UPDATE 1

Android Support Library 23.2.0以降、LayoutManager用にメソッドsetAutoMeasureEnabled(true)が追加されました。これは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は推奨されなくなったので、オーバーライドされたメソッドisAutoMeasureEnabled()を使ってLayoutManagerのカスタム実装を提供するべきです

しかし、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()));

しかし、これら2つのメソッドも呼び出す必要があります。

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

ここではsetNestedScrollingEnabled(false)RecyclerViewのスクロールを無効にしているので、NestedScrollViewからのスクロールイベントをインターセプトしません。そしてsetHasFixedSize(false)はアダプタの内容の変更がRecyclerViewのサイズを変更できると決定します

重要な注意: この解決法は場合によっては少しバグがありパフォーマンスに問題があるので、もしあなたがRecyclerViewにたくさんの項目があるなら、リストビューのカスタムLinearLayoutベースの実装を使うことをお勧めします。それのためのアダプターの類似体そしてそれをListViewまたはRecyclerViewのように振る舞わせる

112
smbd uknow

1)上記のサポートライブラリ23.2.0(または)を使用する必要があります。

2)RecyclerViewの高さはwrap_contentになります。

3)recyclerView.setNestedScrollingEnabled(false)

しかしこれをすることによってリサイクル業者パターンは働かない。 (つまり、wrap_contentは完全なRecyclerViewの高さが必要なので、すべてのビューは一度にロードされます。したがって、すべての子Viewが一度に描画されます。ビューはリサイクルされません)。本当に必要な場合以外は、このパターンutilを使用しないでください。 viewTypeRecyclerViewを使用するのではなく、RecyclerViewを使用し、Scrollviewにスクロールする必要がある他のすべてのビューを追加してください。パフォーマンスへの影響は非常に大きくなります。

わかりやすくするために、「すべての子ビューでLinearLayoutとして機能する」

88
Ashok Varma

Android:fillViewport="true"を使用して、NestedScrollViewRecyclerViewを測定させることができます。 RecyclerViewは残りの高さを埋めます。したがって、NestScrollViewをスクロールしたい場合は、RecyclerViewminHeightを設定できます。

34
zayn

setAdapter自体の前にrecyclerView.setNestedScrollingEnabled(false);を追加するだけで私のために働きました。私はどこにも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>
25
Vignesh Sundar

これは私のために働いているものです

<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>
19
Ness Tyagi

このライブラリを使ってみてください - https://github.com/serso/Android-linear-layout-manager

ライブラリのLayoutManagerはRecyclerViewにその内容をラップさせます。この場合、RecyclerViewは「内側のビューと同じくらいの大きさ」になるので、スクロールバーは表示されず、ユーザーはNestedScrollViewのスクロール機能を使用します。したがって、「スクロール可能な内側のスクロール可能」のようにあいまいになることはありません。

7
alcsan

簡単なテストコードがあります。

<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>
7
Hakim Khan

私は RecyclerView NestedScrollView の中に使って、それは私のために働きました。私が留意しなければならなかった唯一の問題は、NestedScrollViewが1つの子ビューのみをとるということでした。だから私の場合私は自分のRecyclerViewを収納していたLienearLayoutビューグループと私が必要としていた他の多くのビューを使いました。

RecyclerViewをNestedScrollView内に配置するときに問題が1つ発生します。私はRecyclerViewのコンテンツをスクロールするのがゆるいことに気づきました。

私は後でRecyclerViewがスクロールイベントを受信して​​いたため、NestedScrollViewのスクロール動作と競合していたことに気付きました。

そのため、この問題を解決するには、このメソッドでRecyclerViewのスクロール機能を無効にする必要がありましたmovieListNewRecyclerView.setNestedScrollingEnabled(false);

私のInstagramをチェックして、私が実際にしたことの短いビデオを見ることができます。これは私のInstagramのハンドルofelix03です

私がしたことを見るためにこのイメージをクリックしなさい

6
Felix Otoo

スクロールの問題を回避するために使用しているコードは次のとおりです。

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

NestedScrollViewの中にViewpagerとRecyclerViewがあります。以下の行を追加した後

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

私は遅いスクロールとスクロールラグの問題を解決しました。

4
Isham

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);がうまくいくでしょう。

詳細については、 この問題 および この開発者ブログ を参照してください。

3
astuter

入れ子になったスクロールビュー内でリサイクラービューを使用することはできません。これはさらにスクロール可能なビューを含むことを意図したものではありませんが、ネストされたスクロールビューが必要なのは、スクロールレイアウト自体の子だからです。私は同じ問題を抱えていたが、結局私のテキストビューをリサイクラビュー内のヘッダビューにし、リサイクラビューをコーディネータレイアウトの直接の子にし、そしてネストされたスクロールビューを削除した。それから私の問題はすべてなくなりました。

3
Barry Irvine

良い答えがたくさんあります。重要なのは、nestedScrollingEnabledfalseに設定する必要があるということです。前述のように、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" />
1
Alex Misulya

androidxの場合はandroidx.core.widget.NestedScrollViewと呼ばれます。そしてisScrollContainermeasureAllChildrenが有効になっているバターも同様にスクロールします。

<!-- 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>
1
Martin Zeitler

私はツールバーのスクロールを使って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
Bogdan Ustyak

nestedScrollView内でrecyclerViewを使用しないでください。カスケードの問題が発生する可能性があります!複数の種類のビューを処理するために、RecyclerViewでItemViewTypesを使用することをお勧めします。 match_parentの幅と高さでRecyclerViewを追加するだけです。次に、recyclerViewAdapterでgetItemViewTypeをオーバーライドし、位置を使用してどのレイアウトを拡張するかを処理します。その後、onBindViewHolderメソッドを使用してビューホルダーを処理できます。

0
Hossein Karami

RecyclerView ScrollListener inside NestedScrollViewを使用している場合、両方を使用するとaddOnScrollListenerリスナーが正しく機能しません。

このコードを使用してください。

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

このコードは正常に動作していますRecyclerView ScrollListener inside NestedScrollView.

ありがとう

0
Rahul

Recyclerviewのリサイクル機能を維持し、すべてのデータをロードするのにrecyclerviewを回避するための1つの解決策は、recyclerview自体に固定の高さを設定することです。こうすることで、リサイクルビューは、その高さがユーザーに表示される分だけロードされるように制限されます。

0