web-dev-qa-db-ja.com

RecyclerViewのスクロールを無効にするには?

RecyclerViewでスクロールを無効にすることはできません。 rv.setEnabled(false)を呼び出そうとしましたが、それでもスクロールできます。

スクロールを無効にする方法

164
Zsolt Safrany

あなたはこれのためにあなたのリサイクルビューのレイアウトマネージャを上書きすべきです。このようにすると、スクロールが無効になり、他の機能は無効になりません。それでもクリックや他のタッチイベントを処理することができます。例えば:-

元の:

 public class CustomGridLayoutManager extends LinearLayoutManager {
 private boolean isScrollEnabled = true;

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

 public void setScrollEnabled(boolean flag) {
  this.isScrollEnabled = flag;
 }

 @Override
 public boolean canScrollVertically() {
  //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
  return isScrollEnabled && super.canScrollVertically();
 }
}

ここで "isScrollEnabled"フラグを使って、あなたのリサイクルビューのスクロール機能を一時的に有効/無効にすることができます。

また:

スクロールを無効にしてクリックを許可するには、既存の実装を単純にオーバーライドします。

 linearLayoutManager = new LinearLayoutManager(context) {
 @Override
 public boolean canScrollVertically() {
  return false;
 }
};
302
Saurabh Garg

本当の答えは

recyclerView.setNestedScrollingEnabled(false);

ドキュメンテーション に詳細情報

108
Bozic Nebojsa

これは少し厄介な回避策ですが、うまくいきます。 RecyclerViewでスクロールを有効/無効にすることができます。

これは空のRecyclerView.OnItemTouchListenerですべてのタッチイベントを盗み、ターゲットのRecyclerViewを無効にします。

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return true;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

それを使う:

RecyclerView rv = ...
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();

rv.addOnItemTouchListener(disabler);        // disables scolling
// do stuff while scrolling is disabled
rv.removeOnItemTouchListener(disabler);     // scrolling is enabled again 
41
Zsolt Safrany

API 21以降の場合:

Javaコードは不要です。 Android:nestedScrollingEnabled="false"はxmlに設定できます。

<Android.support.v7.widget.RecyclerView
     Android:id="@+id/recycler"
     Android:layout_width="match_parent"
     Android:layout_height="wrap_content"
     Android:clipToPadding="true"
     Android:nestedScrollingEnabled="false"
     tools:listitem="@layout/adapter_favorite_place">
29
Milad Faridnia

これは私のために働く:

  recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
29
alxgarcia

RecyclerView classを継承したクラスを作成する

    public class NonscrollRecylerview extends RecyclerView {

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

public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public NonscrollRecylerview(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
            Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
    ViewGroup.LayoutParams params = getLayoutParams();
    params.height = getMeasuredHeight();
}
}

これはscrollイベントを無効にしますが、clickイベントは無効にしません

XMLでこれを使用して、次のことを行います。

  <com.yourpackage.xyx.NonscrollRecylerview 
 ...
 ... >

 ...
 ...

</com.yourpackage.xyz.NonscrollRecylerview >
8
Ashish

RecyclerViewスクロール機能のみを無効にするだけの場合は、RecyclerViewsetLayoutFrozen(true);メソッドを使用できます。しかし、それはタッチイベントを無効にすることはできません。

your_recyclerView.setLayoutFrozen(true);
7
Ekta Bhawsar

もう一つの選択肢はsetLayoutFrozenですが、他にもたくさんの副作用があります。

https://developer.Android.com/reference/Android/support/v7/widget/RecyclerView.html#setLayoutFrozen(boolean)

5
Taig

RecyclerViewを凍結することでスクロールを無効にすることができます。

フリーズするには:recyclerView.setLayoutFrozen(true)

解凍するには:recyclerView.setLayoutFrozen(false)

5
Virat Singh
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            // Stop only scrolling.
            return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
        }
    });
5
rajesh

スクロールを無効にするには、LayoutManagerを拡張し、canScrollHorizontally()canScrollVertically()をオーバーライドします。

先頭に項目を挿入しても自動的に先頭に戻ることはありません。これを回避するには、次のようにします。

  private void clampRecyclerViewScroll(final RecyclerView recyclerView)
  {
    recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
    {
      @Override
      public void onItemRangeInserted(int positionStart, int itemCount)
      {
        super.onItemRangeInserted(positionStart, itemCount);
        // maintain scroll position at top
        if (positionStart == 0)
        {
          RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
          if (layoutManager instanceof GridLayoutManager)
          {
            ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }else if(layoutManager instanceof LinearLayoutManager)
          {
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }
        }
      }
    });
  }
4
Aidanvii

私はこれがすでに受け入れられた答えを持っていることを知っています、しかし解決策は私が遭遇したユースケースを考慮に入れていません。

私は特にまだクリック可能で、まだRecyclerViewのスクロール機構を無効にしたヘッダ項目を必要としていました。これは次のコードで実現できます。

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                    @Override
                    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                        return e.getAction() == MotionEvent.ACTION_MOVE;
                    }

                    @Override
                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

                    }

                    @Override
                    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

                    }
                });
3
Ryan Simon

コトリンバージョンを書きました:

class NoScrollLinearLayoutManager(context: Context?) : LinearLayoutManager(context) {
    private var scrollable = true

    fun enableScrolling() {
        scrollable = true
    }

    fun disableScrolling() {
        scrollable = false
    }

    override fun canScrollVertically() =
            super.canScrollVertically() && scrollable


    override fun canScrollHorizontally() =
            super.canScrollVertically()

 && scrollable
}

使用法:

recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
3

OnTouchEvent()とonInterceptTouchEvent()をオーバーライドし、OnItemTouchListenerがまったく必要ない場合はfalseを返します。これはViewHoldersのOnClickListenerを無効にしません。

public class ScrollDisabledRecyclerView extends RecyclerView {
    public ScrollDisabledRecyclerView(Context context) {
        super(context);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }
}
2
ypresto

何らかの理由で@Alejandro Graciaの回答が数秒後に始まった。私は即座にRecyclerViewをブロックする解決策を見つけました:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                return true;
            }
            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {
            }
            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
            }
        });
2
vovahost

XMLの場合: - /

あなたは付け加えられます

Android:nestedScrollingEnabled="false"

子RecyclerViewレイアウトXMLファイル内

または

Javaの場合: - /

childRecyclerView.setNestedScrollingEnabled(false);

javaコードであなたのRecyclerViewに。

ViewCompat(Java)を使用して: -

childRecyclerView.setNestedScrollingEnabled(false); Android_version> 21 devicesでのみ動作します。すべてのデバイスで動作するためには、以下を使用してください

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);

2
jafarbtech

アダプタを設定した後にこの行を追加することができます

ViewCompat.setNestedScrollingEnabled(recyclerView, false);

これで、リサイクルビューがスムーズなスクロールで機能するようになります

1
Atefeh Srch

私は数時間この問題に取り組んできたので、私は私の経験を共有したいと思います、layoutManagerソリューションのためにそれは大丈夫ですが再利用可能にしたいのであればリサイクル業者を上に戻るでしょう。

現時点での最良の解決策は(少なくとも私にとっては)@Zsolt Safranyメソードを使用することですが、getIterおよびsetterを追加するので、OnItemTouchListenerを削除または追加する必要はありません。

次のように

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    boolean isEnable = true;

    public RecyclerViewDisabler(boolean isEnable) {
        this.isEnable = isEnable;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return !isEnable;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {}

   @Override
   public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept){}
 }

使用法

RecyclerViewDisabler disabler = new RecyclerViewDisabler(true);
feedsRecycler.addOnItemTouchListener(disabler);

// TO ENABLE/DISABLE JUST USE THIS
disabler.setEnable(enable);
1
Aladdin

本当に簡単な答えがあります。

LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
                @Override
                public boolean canScrollVertically() {
                    return false;
                }
            };

上記のコードは、RecyclerViewの垂直スクロールを無効にします。

1
Emi Raz

複数のRecycleViewを含むフラグメントを見つけたので、各RecycleViewには1つのスクロールバーではなく1つのスクロールバーしか必要ありません。

そのため、ScrollViewを2つのRecycleViewを含む親コンテナに配置し、RecycleViewでAndroid:isScrollContainer="false"を使用します。

<Android.support.v7.widget.RecyclerView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    app:layoutManager="LinearLayoutManager"
    Android:isScrollContainer="false" />
0
pk028382

標準的な機能だけを使用して、スクロールを無効にするより直接的な方法があります。 RecyclerViewaddOnScrollListener(OnScrollListener listener)と呼ばれるメソッドを持っています、そしてこれだけを使うことでスクロールを止めることができます。

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

ユースケース: RecyclerView内のアイテムの1つをクリックしたときにスクロールを無効にして、誤って別のアイテムにスクロールしても邪魔されずにアクションを実行できるとしましょう。それは、スクロールを有効にするためにもう一度アイテムをクリックするだけです。そのためには、OnClickListenerRecyclerView内のすべての項目に添付します。したがって、項目をクリックすると、isItemSelectedfalseからtrueに切り替わります。このようにスクロールしようとすると、RecyclerViewは自動的にメソッドonScrollStateChangedを呼び出し、isItemSelectedtrueに設定されているので、RecyclerViewがチャンスを得る前にすぐに停止します。

注:使い勝手を良くするために、GestureListenerクリックを防ぐためにOnClickListenerではなくaccidentalを使用してください。

0
Tim Jorjev

これがデータバインディングを使った方法です。

            <Android.support.v7.widget.RecyclerView
                Android:id="@+id/recycler_view"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:clipChildren="false"
                Android:onTouch="@{(v,e) -> true}"/>

「true」の代わりに、条件に基づいて変更されたブール変数を使用したため、リサイクラビューは無効と有効の間で切り替わります。

0
bwhite

これをxmlのrecycleviewに追加するだけです。

 Android:nestedScrollingEnabled="false"

このような

<Android.support.v7.widget.RecyclerView
                    Android:background="#ffffff"
                    Android:id="@+id/myrecycle"
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent"
                    Android:nestedScrollingEnabled="false">
0
anas

追加する

Android:descendantFocusability="blocksDescendants"

srollViewまたはNestedScrollView(およびListView、recyclerview、gridviewのいずれかの親)の子に

0
Pankaj Talaviya