J'ai une ViewPager
qui instancie une View
. Je souhaite désactiver le défilement du visualiseur et des boutons enfants pendant qu'un résultat de recherche est renvoyé à la vue. J'ai appelé viewPager.setEnabled(false)
mais cela ne le désactive pas.
Quelqu'un a une idée?
Une solution simple consiste à créer votre propre sous-classe de ViewPager
dotée d'un indicateur private boolean
, isPagingEnabled
. Puis substituez les méthodes onTouchEvent
et onInterceptTouchEvent
. Si isPagingEnabled
est égal à true, appelez la méthode super
, sinon 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;
}
}
Puis, dans votre fichier Layout.XML
, remplacez les balises <com.Android.support.V4.ViewPager>
par les balises <com.yourpackage.CustomViewPager>
.
Ce code a été adapté de ce blog post .
Il y a une solution facile pour celui-ci:
Lorsque vous souhaitez désactiver le défilement du viewpager, procédez comme suit:
mViewPager.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
return true;
}
});
Et quand vous voulez le réactiver, alors:
mViewPager.setOnTouchListener(null);
Cela fera l'affaire.
Voici ma variante légère de la réponse 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);
}
}
Avec mon code, vous pouvez désactiver la pagination avec setEnable()
.
J'ai trouvé une solution simple.
//disable swiping
mViewPager.beginFakeDrag();
//enable swiping
mViewPager.endFakeDrag();
Je suggère une autre façon de résoudre ce problème. L'idée consiste à envelopper votre viewPager dans une scrollView, de sorte que lorsque cette scrollView ne peut pas défiler, votre viewPager ne le soit pas non plus.
Voici ma mise en page 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>
Aucun code requis.
Fonctionne bien pour moi.
Pour désactiver le balayage
mViewPager.beginFakeDrag();
Pour activer le balayage
mViewPager.endFakeDrag();
La meilleure solution qui a fonctionné pour moi est:
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;
}
}
Après cela, le défilement sera désactivé au toucher et vous pourrez toujours utiliser la méthode setCurrentItem
pour changer de page.
Que dis-tu de ça :
J'ai utilisé CustomViewPager
et ensuite, surcharger la méthode scrollTo
J'ai vérifié le mouvement lorsque je faisais beaucoup de petits coups, cela ne défilait pas vers d'autres pages.
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);
}
}
}
La réponse de Slayton fonctionne bien. Si vous voulez arrêter de glisser comme un singe, vous pouvez remplacer un 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;
}
}
Donc, vous ne pouvez que glisser côte à côte
Lorsque vous utilisez la réponse ci-dessus, vous pouvez être confronté à une mauvaise question: "set isScrollEnabled false, certaines vues de ce viewPager ne peuvent pas gérer onClick & onTouchEvent. Je vous présente donc ma solution, j'espère que cela pourra vous aider ...
class WrapContentViewPager @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null) : ViewPager(context, attrs) {
var isScrollEnabled = true
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
if(isScrollEnabled){
super.onInterceptTouchEvent(event)
}else{
return isScrollEnabled && super.onInterceptTouchEvent(event)
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
if(isScrollEnabled){
return isScrollEnabled
}else{
return isScrollEnabled && super.onTouchEvent(event)
}
}
}
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*/);
}
}
}
Ensuite, dans votre fichier Layout.XML, remplacez les balises --- com.Android.support.V4.ViewPager --- Par des balises --- com.yourpackage.NonSwipeableViewPager ---.
Remplacer uniquement onTouchEvent et onInterceptTouchEvent n'est pas suffisant si ViewPager est lui-même dans un autre ViewPager.
ViewPager enfant ferrait des événements tactiles avec défilement horizontal à partir du ViewPager parent, à moins qu’il ne soit positionné sur sa première/dernière page.
Voir plus dans cette SO réponse
La nouvelle classe ViewPager2 d'androidx permet de désactiver le défilement avec la méthode setUserInputEnabled (false)
private val pager: ViewPager2 by bindView(R.id.pager)
override fun onCreate(savedInstanceState: Bundle?) {
pager.isUserInputEnabled = false
}
Voici une réponse dans Kotlin et 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)
}
}