É possível desativar a rolagem em um ViewPager

138

Eu tenho um ViewPagerque instancia a View. Gostaria de desativar momentaneamente a rolagem do visor e os botões filho enquanto um resultado de pesquisa é retornado à visualização. Estou ligando, viewPager.setEnabled(false)mas isso não o desativa.

Alguém tem alguma idéia?

mAndroid
fonte

Respostas:

355

Uma solução simples é criar sua própria subclasse de ViewPagerque possui uma private booleanbandeira isPagingEnabled,. Em seguida, substitua os métodos onTouchEvente onInterceptTouchEvent. Se isPagingEnabledigual a true, invoque o supermétodo, caso contrário 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;
    }
}

Em seguida, no seu Layout.XMLarquivo, substitua as <com.android.support.V4.ViewPager>tags por <com.yourpackage.CustomViewPager>tags.

Este código foi adaptado desta postagem do blog .

Slayton
fonte
2
solução greate, funciona bem. Se você deseja parar de deslizar como um macaco, é possível substituir um OnPageChangeListener por @Override public void onPageScrollStateChanged (estado final int) {switch (state) {case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled (false); pausa; caso ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled (true); pausa; } // noop}
Informatic0re
13
PS: No XML, use <yourpkgname.CustomViewPager ... em vez de <com.android, support.v4.ViewPager ... #
thecr0w
Para adicionar outra solução semelhante, você pode usar a biblioteca chamada "JazzyViewPager": github.com/jfeinstein10/JazzyViewPager , e apenas chamar setPagingEnabled (boolean)
desenvolvedor Android
é possível parar de rolar apenas para a direita? i pode rolagem só deixou
Saif Hamed
Ainda é possível "rolar" focando elementos (botões, etc.) nas páginas ao usar um controle de jogo ou teclado, por exemplo. Como desativar isso completamente? Eu acho que é um outro tipo de evento que deve ser interceptadas ...
David Ferrand
34

Existe uma solução fácil para este:

Quando você deseja desativar a rolagem do viewpager:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

E quando você deseja reativá-lo, então:

mViewPager.setOnTouchListener(null);

Isso será o suficiente.

Akhil Sekharan
fonte
46
Quase, mas não exatamente. O toque para baixo ainda acontece, para que você possa mover as páginas fazendo vários pequenos deslizamentos.
Flynny75
@Akhil Sekharan Estava enfrentando o problema exatamente com o que Flynny está enfrentando ao usar esta resposta ... mas, felizmente, não sei como de repente esse erro ocorreu .. :) e funcionou como um encanto!
Zombie
Você pode fazer os lotes de pequenos furtos assim você ainda tem a mais onInterceptTouchEvent boolean pública (evento MotionEvent) {passeio como por slatons responder
Ryan Heitner
28

Aqui está minha variante leve da resposta de slayton:

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);
    }
}

Com o meu código, você pode desativar a paginação com setEnable().

rekire
fonte
A substituição onInterceptTouchEvent()impedirá que as visualizações secundárias recebam entrada. Na maioria dos casos, esse não é o comportamento pretendido.
Alex Semeniuk
19

Encontrei uma solução simples.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
Yessy
fonte
Esse é todo o código que você usou? Isso não está funcionando para mim.
precisa saber é o seguinte
17
Não funciona para mim. Ainda pode fazer muitos pequenos golpes.
DYS
Este código não é bcz adequada É rolagem muito lentamente como a vista de suspensão
Ghanshyam Nayma
Isso pode funcionar por sorte. Atualizar para o ViewPager pode quebrar esse hack.
Pointer Null
Ainda está arrastando, mas pouco a pouco (.
ekashking 5/11/19
14

Sugiro outra maneira de resolver esse problema. A idéia é agrupar seu viewPager por um scrollView, para que, quando esse scrollView não for rolável, seu viewPager também não seja rolável.

Aqui está o meu layout 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>

Nenhum código é necessário.

Funciona bem para mim.

M. Marmor
fonte
1
Entre todas essas respostas, acho que isso é simples e funciona muito bem !!
SREE
OK ... mas quando você tem um mapa como um dos fragmento em ViewPager então ... é um problema
ekashking
4

Para desativar o furto

 mViewPager.beginFakeDrag();

Para ativar o furto

 mViewPager.endFakeDrag();
Isaias Carrera
fonte
2
A rolagem ainda é possível, apenas não é mais fluente. Basicamente, isso apenas piora a qualidade sem resolver o problema.
Benjamin Basmaci 14/03/19
1
resposta duplicada
Ricardo A.
3

A melhor solução que funcionou para mim é:

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;
    }
}

Depois disso, a rolagem será desativada pelo toque e você ainda poderá usar o setCurrentItemmétodo para alterar a página.

Pradeep Kumar Kushwaha
fonte
Não sei por que, mas simplesmente não funcionou. A rolagem ainda acontece.
Ricardo A.
1
O canScrollHorizontally()método não tem efeito no cenário atual. Nem é chamado quando o furto acontece.
Alex Semeniuk
3

Aqui está uma resposta em Kotlin e 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)
    }
}
Pasi Matalamäki
fonte
2

Que tal isso:
eu usei CustomViewPager
e, em seguida, substituo o scrollTo, para o método que
eu verifiquei o movimento ao fazer muitos pequenos furtos, ele não rola para outras páginas.

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);
       }
    }
}
tchau
fonte
Eu tinha o problema de que o espectador ainda estava fazendo pequenos furtos, mas a substituição View.scrollTo(int x, int y)resolveu esse problema para mim. Obrigado
Palm
Causa algum comportamento estranho em alguns casos. Como ir ao vazio e deixar apenas uma página em branco '-'
Ricardo A.
2

No meu caso de usar o ViewPager 2 alfa 2, o trecho abaixo funciona

viewPager.isUserInputEnabled = false

Capacidade de desativar a entrada do usuário (setUserInputEnabled, isUserInputEnabled)

consulte isso para obter mais alterações no viewpager2 1.0.0-alpha02

Também foram feitas algumas alterações na versão mais recente do ViewPager 2 alpha 4

orientação e os atributos isUserScrollable não fazem mais parte do SavedState

consulte isso para obter mais alterações no viewpager2 # 1.0.0-alpha04

Piyush Johnson
fonte
1

A nova classe ViewPager2 do androidx permite desativar a rolagem com o método setUserInputEnabled (false)

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

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

A resposta de slayton funciona bem. Se você deseja parar de deslizar como um macaco, você pode substituir um OnPageChangeListener por

@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; 
        } 
    }

Então você só pode deslizar lado a lado

Informatic0re
fonte
1
Não encontraram qualquer método de ViewPager tais como setPagingEnabled (valor booleano)
Rakesh Yadav
setPagingEnabled (valor booleano) deve ser criado por você, pois não existe esse método para substituir.
quer
Não está claro o que esse setPagingEnabled()método faz. Por favor inclua o código completo.
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*/);
    }
}
}

Em seguida, no arquivo Layout.XML, substitua as tags --- com.android.support.V4.ViewPager --- por --- com.yourpackage.NonSwipeableViewPager ---.

masoud jabbarian
fonte