ViewPagerのスクロールを無効にすることは可能ですか


138

ViewPagerインスタンス化するがありますView。検索結果がビューに返される間、ビューページャーと子ボタンの両方のスクロールを一時的に無効にしたいのですが。電話をかけましたviewPager.setEnabled(false)が、これで無効になりません。

誰かアイデアはありますか?


回答:


355

簡単な解決策はViewPagerprivate booleanフラグを持つ独自のサブクラスを作成することisPagingEnabledです。次にonTouchEventおよびonInterceptTouchEventメソッドをオーバーライドします。isPagingEnabledtrueの場合はsuperメソッドを呼び出し、それ以外の場合はを呼び出しますreturn

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

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

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

次に、Layout.XMLファイル内の<com.android.support.V4.ViewPager>タグを<com.yourpackage.CustomViewPager>タグに置き換えます。

このコードは、このブログ投稿から適応されました。


2
greateソリューション、正常に動作します。サルのようにスワイプを停止したい場合は、@ OverrideでOnPageChangeListenerをオーバーライドできますpublic void onPageScrollStateChanged(final int state){switch(state){case ViewPager.SCROLL_STATE_SETTLING:mPager.setPagingEnabled(false); ブレーク; ケースViewPager.SCROLL_STATE_IDLE:mPager.setPagingEnabled(true); ブレーク; } // noop}
Informatic0re

13
PS:XMLでは、<com.android、support.v4.ViewPager ...の代わりに<yourpkgname.CustomViewPager ...を使用してください
thecr0w

別の同様のソリューションを追加するには、「JazzyViewPager」と呼ばれるライブラリを使用できます:github.com/jfeinstein10/JazzyViewPager、そしてsetPagingEnabled(boolean)を呼び出すだけです
android developer

右スクロールのみを停止することは可能ですか?私は左にのみスクロールできます
Saif Hamed 2014

たとえばゲームコントローラやキーボードを使用しているときに、ページ内の要素(ボタンなど)にフォーカスすることで、引き続き「スクロール」することができます。それを完全に無効にする方法は?インターセプトする必要がある別のタイプのイベントだと思います...
David Ferrand

34

これには簡単な修正があります:

ビューページャーのスクロールを無効にしたい場合:

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

そして、それを再び有効にしたいときは:

mViewPager.setOnTouchListener(null);

これでうまくいきます。


46
ほぼ、しかし完全ではありません。タッチダウンは引き続き行われるため、多数の小さなスワイプでページを移動できます。
Flynny75

@Akhil Sekharanこの回答を使用したとき、Flynnyが直面している問題に正確に直面していましたが、幸いにも、そのエラーが突然起こったことがわかりません。
ゾンビ

たくさんの小さなスワイプを行うことができるので、公開ブール値onInterceptTouchEvent(MotionEvent event)をオーバーする必要があります{スラトンごとに乗る
Ryan

28

スレイトンの答えの私の軽量版は次のとおりです。

public class DeactivatableViewPager extends ViewPager {
    public DeactivatableViewPager(Context context) {
        super(context);
    }

    public DeactivatableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !isEnabled() || super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return isEnabled() && super.onInterceptTouchEvent(event);
    }
}

私のコードでは、でページングを無効にできますsetEnable()


オーバーライドonInterceptTouchEvent()すると、子ビューが入力を受け取ることができなくなります。ほとんどの場合、これは意図された動作ではありません
Alex Semeniuk

19

簡単な解決策を見つけました。

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

これはあなたが使用したすべてのコードですか?これは私のために働いていません。
Jared Burrows、

17
うまくいきません。まだたくさんの小さなスワイプができます。
DYS 2015年

このコードは適切ではありませんbczハンギングビューのように非常にゆっくりとスクロールします
Ghanshyam Nayma

これは運でうまくいくかもしれません。ViewPagerを更新すると、このハックを壊すことができます。
Pointer Null

それはまだ(ドラッグが、少しずつだ。
ekashking

14

この問題を解決する別の方法を提案します。この考えは、viewPagerをscrollViewでラップすることです。そのため、このscrollViewがスクロールできない場合、viewPagerもスクロールできません。

これが私のXMLレイアウトです:

        <HorizontalScrollView
            android:id="@+id/horizontalScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true" >

            <android.support.v4.view.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

コードは必要ありません。

私にとってはうまくいきます。


1
これらすべての答えの中で、これは単純でうまく機能していると思います!!
SREE

OK ...しかし、ViewPagerにフラグメントの1つとしてマップがある場合、それは...問題です
ekashking

4

スワイプを無効にするには

 mViewPager.beginFakeDrag();

スワイプを有効にするには

 mViewPager.endFakeDrag();

2
スクロールはまだ可能ですが、もはや流暢ではありません。これは基本的に問題を解決せずに品質を悪化させるだけです。
ベンジャミンバスマシ

1
重複した回答
リカルドA.

3

私にとってうまくいった最善の解決策は:

public class DeactivatedViewPager extends ViewPager {

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

    public DeactivatedViewPager (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

この後、スクロールはタッチで無効になり、setCurrentItemメソッドを使用してページを変更できます。


理由は不明ですが、機能しませんでした。スクロールはまだ起こります。
Ricardo A.

1
このcanScrollHorizontally()方法は、現在のシナリオでは効果がありません。スワイプが発生しても呼び出されません。
Alex Semeniuk

3

これがKotlinとandroidXの答えです

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}

2

どのようにこのことについて:
私が使用CustomViewPager
して次、scrollTo方法オーバーライドする
小さなスワイプの多くを行っているとき、私は動きをチェックし、それが他のページにスクロールしません。

public class CustomViewPager extends ViewPager {

    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

    public void setPagingEnabled(boolean enabled) {
        this.enabled = enabled;
    } 

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}

ビューページャーがまだ少しスワイプしているという問題がありましたが、オーバーライドすることで View.scrollTo(int x, int y)この問題は解決しました。 ありがとう
Palm

場合によっては、奇妙な動作が発生します。ボイドに行って空白ページ '-'だけを残すように
Ricardo A.

2

ViewPager 2 alpha 2を使用している私の場合、以下のスニペットが機能します

viewPager.isUserInputEnabled = false

ユーザー入力を無効にする機能(setUserInputEnabled、isUserInputEnabled)

viewpager2 1.0.0-alpha02のその他の変更については、これを参照してください

また、いくつかの変更は最新バージョンのViewPager 2 alpha 4で行われました

orientationおよびisUserScrollable属性は、SavedStateの一部ではなくなりました

viewpager2#1.0.0-alpha04のその他の変更については、これを参照してください


1

androidxの新しいクラスViewPager2では、メソッドsetUserInputEnabled(false)でスクロールを無効にできます

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}

0

スレイトンの答えはうまくいきます。サルのようにスワイプを停止したい場合は、OnPageChangeListenerを次のようにオーバーライドできます。

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

だから、並べてスワイプするだけです


1
setPagingEnabled(boolean value)などのViewPagerのメソッドは見つかりませんでした
Rakesh Yadav

setPagingEnabled(boolean value)は、オーバーライドするメソッドがないため、ユーザーが作成します。
Kharak、2017

このsetPagingEnabled()メソッドが何をするかは不明です。完全なコードを含めてください。
Alex Semeniuk

0
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;

public class NonSwipeableViewPager extends ViewPager {

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

public NonSwipeableViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

private void setMyScroller() {
    try {
        Class<?> viewpager = ViewPager.class;
        Field scroller = viewpager.getDeclaredField("mScroller");
        scroller.setAccessible(true);
        scroller.set(this, new MyScroller(getContext()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public class MyScroller extends Scroller {
    public MyScroller(Context context) {
        super(context, new DecelerateInterpolator());
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int 
duration) {
        super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
    }
}
}

次に、Layout.XMLファイルで--- com.android.support.V4.ViewPager ---タグを--- com.yourpackage.NonSwipeableViewPager ---タグに置き換えます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.