でのスクロールを無効にできませんRecyclerView
。電話をかけrv.setEnabled(false)
てみましたが、スクロールできます。
スクロールを無効にするにはどうすればよいですか?
View
てRecyclerView
、の上に透明部分を置いたVISIBLE
とGONE
思いますが、袖口を外すと、あなたのアプローチは妥当なようです。
でのスクロールを無効にできませんRecyclerView
。電話をかけrv.setEnabled(false)
てみましたが、スクロールできます。
スクロールを無効にするにはどうすればよいですか?
View
てRecyclerView
、の上に透明部分を置いたVISIBLE
とGONE
思いますが、袖口を外すと、あなたのアプローチは妥当なようです。
回答:
このためには、recycleviewのlayoutmanagerをオーバーライドする必要があります。このようにして、スクロールを無効にするだけで、他の機能は無効にします。クリックやその他のタッチイベントは引き続き処理できます。例えば:-
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;
}
};
NestedScrollView
:android.support.v4.widget.NestedScrollView
:、ここで説明したように、chessdorkによってstackoverflow.com/questions/37846245/...
REAL REALの答えは次のとおり です。API21以降の場合:
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
。
これは、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
これは私にとってはうまくいきます:
recyclerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
Custom view 'RecyclerView' has setOnTouchListener called on it but does not override performClick
return e.getAction() == MotionEvent.ACTION_MOVE;
代わりにreturn true;
、スクロール/スワイプイベントのみがキャンセルされるのではなく。
RecyclerViewをフリーズすることでスクロールを無効にできます。
凍結するには:
recyclerView.setLayoutFrozen(true)
解凍するには: recyclerView.setLayoutFrozen(false)
拡張クラスを作成RecyclerViewのクラスを
public class NonScrollRecyclerView extends RecyclerView {
public NonScrollRecyclerView(Context context) {
super(context);
}
public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public NonScrollRecyclerView(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();
}
}
これはスクロールイベントを無効にしますが、クリックイベントは無効にしません
これをXMLで使用して、以下を実行します。
<com.yourpackage.xyx.NonScrollRecyclerView
...
...
/>
あなただけ無効にした場合のみ、スクロール機能のRecyclerView
あなたが使用できるsetLayoutFrozen(true);
方法をRecyclerView
。ただし、タッチイベントを無効にすることはできません。
your_recyclerView.setLayoutFrozen(true);
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
// Stop only scrolling.
return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
}
});
もう1つの方法はですがsetLayoutFrozen
、他の副作用もたくさんあります。
コトリン版を書いた:
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()
を拡張し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) {
}
});
XMLで:-
あなたは付け加えられます
android:nestedScrollingEnabled="false"
子RecyclerViewレイアウトXMLファイル内
または
Javaで:-
childRecyclerView.setNestedScrollingEnabled(false);
JavaコードでRecyclerViewに。
ViewCompat(Java)の使用:-
childRecyclerView.setNestedScrollingEnabled(false);
android_version> 21デバイスでのみ機能します。すべてのデバイスで作業するには、次を使用します
ViewCompat.setNestedScrollingEnabled(childRecyclerView, 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) {
}
});
onTouchEvent()とonInterceptTouchEvent()をオーバーライドし、OnItemTouchListenerがまったく必要ない場合はfalseを返します。これはViewHoldersのOnClickListenersを無効にしません。
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;
}
}
アダプタを設定した後でこの行を追加できます
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
これで、recyclerviewはスムーズスクロールで動作します
私はこの問題で数時間苦労してきました。そこで、私の経験を共有したいと思います。layoutManagerソリューションの場合は問題ありませんが、再有効化したい場合は、リサイクラーを上にスクロールしてスクロールします。
これまでの最善の解決策は(少なくとも私にとっては)@Zsolt Safranyメソッドを使用することですが、ゲッターとセッターを追加することで、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);
これは、データバインディングを使用してどのように実行したかです。
<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」の代わりに、条件に基づいて変更されるブール変数を使用して、リサイクラービューが無効と有効との間で切り替わるようにしました。
複数のRecycleViewを含むフラグメントに遭遇したため、各RecycleViewに1つのスクロールバーではなく、1つのスクロールバーしか必要ありません。
したがって、2つのRecycleViewを含む親コンテナーにScrollViewを配置して、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
。
stopScroll()
スクロールをフリーズするのではなく、スクロールrecyclerviewを停止/停止するだけです。
isItemSelected
設定してスクロールしようとするたびに停止しtrue
ます。それ以外の場合は、スクロールを無効にするにはカスタムRecyclerViewが必要です。このソリューションが提供する追加機能が少しだけ必要だったので、それを避けたかったのです。
タッチによるスクロールを停止するが、コマンドを介してスクロールを続ける場合:
if(appTopBarMessagesRV == null){appTopBarMessagesRV = findViewById(R.id.mainBarScrollMessagesRV);
appTopBarMessagesRV.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if ( rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING)
{
// Stop scrolling by touch
return false;
}
return true;
}
});
}
RecyclerView
スクロールしたくない場合の使用目的は何ですか?