RecyclerView
でスクロールを無効にすることはできません。 rv.setEnabled(false)
を呼び出そうとしましたが、それでもスクロールできます。
スクロールを無効にする方法
あなたはこれのためにあなたのリサイクルビューのレイアウトマネージャを上書きすべきです。このようにすると、スクロールが無効になり、他の機能は無効になりません。それでもクリックや他のタッチイベントを処理することができます。例えば:-
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;
}
};
これは少し厄介な回避策ですが、うまくいきます。 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
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">
これは私のために働く:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
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 >
RecyclerView
のスクロール機能のみを無効にするだけの場合は、RecyclerView
のsetLayoutFrozen(true);
メソッドを使用できます。しかし、それはタッチイベントを無効にすることはできません。
your_recyclerView.setLayoutFrozen(true);
もう一つの選択肢はsetLayoutFrozen
ですが、他にもたくさんの副作用があります。
RecyclerViewを凍結することでスクロールを無効にすることができます。
フリーズするには:recyclerView.setLayoutFrozen(true)
解凍するには:recyclerView.setLayoutFrozen(false)
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
// Stop only scrolling.
return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
}
});
スクロールを無効にするには、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);
}
}
}
});
}
私はこれがすでに受け入れられた答えを持っていることを知っています、しかし解決策は私が遭遇したユースケースを考慮に入れていません。
私は特にまだクリック可能で、まだ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) {
}
});
コトリンバージョンを書きました:
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()
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;
}
}
何らかの理由で@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) {
}
});
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);
アダプタを設定した後にこの行を追加することができます
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
これで、リサイクルビューがスムーズなスクロールで機能するようになります
私は数時間この問題に取り組んできたので、私は私の経験を共有したいと思います、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);
本当に簡単な答えがあります。
LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
@Override
public boolean canScrollVertically() {
return false;
}
};
上記のコードは、RecyclerViewの垂直スクロールを無効にします。
複数の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" />
標準的な機能だけを使用して、スクロールを無効にするより直接的な方法があります。 RecyclerView
はaddOnScrollListener(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つをクリックしたときにスクロールを無効にして、誤って別のアイテムにスクロールしても邪魔されずにアクションを実行できるとしましょう。それは、スクロールを有効にするためにもう一度アイテムをクリックするだけです。そのためには、OnClickListener
をRecyclerView
内のすべての項目に添付します。したがって、項目をクリックすると、isItemSelected
がfalse
からtrue
に切り替わります。このようにスクロールしようとすると、RecyclerView
は自動的にメソッドonScrollStateChanged
を呼び出し、isItemSelected
はtrue
に設定されているので、RecyclerView
がチャンスを得る前にすぐに停止します。
注:使い勝手を良くするために、GestureListener
クリックを防ぐためにOnClickListener
ではなくaccidental
を使用してください。
これがデータバインディングを使った方法です。
<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」の代わりに、条件に基づいて変更されたブール変数を使用したため、リサイクラビューは無効と有効の間で切り替わります。
これを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">
追加する
Android:descendantFocusability="blocksDescendants"
srollViewまたはNestedScrollView(およびListView、recyclerview、gridviewのいずれかの親)の子に