In che modo disabilitare il paging scorrendo con il dito in ViewPager ma riuscendo comunque a scorrere programmaticamente?


550

Ho ViewPager e sotto ho 10 pulsanti. Facendo clic sul pulsante, ad esempio n. 4, il cercapersone passa immediatamente alla pagina n. 4 di mPager.setCurrentItem(3);. Ma voglio disabilitare il paging scorrendo con il dito in orizzontale. Pertanto, il paging viene eseguito SOLO facendo clic sui pulsanti. Quindi, come posso disabilitare lo scorrimento con il dito?


Che ne dici di usare ViewFlipper in primo luogo? Ti farà risparmiare un sacco di mal di testa.
Alex Semeniuk,

Risposte:


885

Devi sottoclassare ViewPager. onTouchEventha un sacco di cose buone che non vuoi cambiare come permettere alle viste dei bambini di ottenere tocchi. onInterceptTouchEventè quello che vuoi cambiare. Se guardi il codice per ViewPager, vedrai il commento:

    /*
     * This method JUST determines whether we want to intercept the motion.
     * If we return true, onMotionEvent will be called and we do the actual
     * scrolling there.
     */

Ecco una soluzione completa:

Per prima cosa, aggiungi questa classe alla tua srccartella:

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

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    //down one is added for smooth scrolling

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

Quindi, assicurati di utilizzare questa classe anziché la normale ViewPager, che probabilmente hai specificato come android.support.v4.view.ViewPager. Nel tuo file di layout, ti consigliamo di specificarlo con qualcosa del tipo:

<com.yourcompany.NonSwipeableViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

Questo esempio particolare è in a LinearLayouted è pensato per occupare l'intero schermo, motivo per cui layout_weightè 1 elayout_height è 0dp.

E il setMyScroller();metodo è per una transizione graduale


3
@louielouie Nota a margine: c'è qualche motivo particolare, perché hai scelto la soluzione 0dpaltezza / 1peso piuttosto che match_parentaltezza per ottenere l'effetto schermo intero? In questo modo ottieni miglioramenti delle prestazioni?
ubuntudroid,

29
Questa risposta non impedisce lo scorrimento della pagina quando si usano i tasti sinistra / destra della tastiera (provarlo nell'emulatore). Potrebbe non essere un problema per i dispositivi touch ma con TV e laptop potrebbe esserlo.
Vincent Mimoun-Prat,

8
@MarvinLabs @Thorbear Il modo corretto per disabilitare lo scorrimento della pagina tramite tastiera è quello di sostituire executeKeyEvent(). Questo è il metodo che poi chiama allowScroll(). // Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
araks

6
beh, questo disabilita anche lo scorrimento verticale ... questo è male, se stai usando le viewlist.
Maysi,

5
Spero che Google abbia appena fornito un metodo al quale forniamo il nostro metodo di interfaccia su come gestire i tocchi / lo scorrimento perché credo che non farebbe male?
Neon Warge,

466

L'estensione più generale di ViewPagersarebbe quella di creare un SetPagingEnabledmetodo in modo da poter abilitare e disabilitare il paging al volo. Per abilitare / disabilitare lo scorrimento, basta ignorare due metodi: onTouchEvente onInterceptTouchEvent. Entrambi restituiranno "false" se il paging è stato disabilitato.

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

Quindi selezionare questo invece del viewpager integrato in XML

<mypackage.CustomViewPager 
    android:id="@+id/myViewPager" 
    android:layout_height="match_parent" 
    android:layout_width="match_parent" />

Devi solo chiamare il setPagingEnabledmetodo con falsee gli utenti non saranno in grado di scorrere per impaginare.


3
Funziona perfettamente per una vista che ha diverse viste secondarie in cui si utilizza lo scorrimento orizzontale (ad es. Grafico AChartEngine). Nel mio frammento utilizzo un callback per la mia attività che gli dice di disattivare o disattivare il paging a seconda che l'utente abbia toccato (ACTION_MOVE) il grafico o l'abbia lasciato (ACTION_CANCEL). Molte grazie!
Riper

32
È possibile semplificare le onTouchEvente onInterceptTouchEventmetodi conreturn enabled && super.onTouchEvent(event);
nbarraille

2
@nbarraille è solo una questione di stile. Puoi usare qualunque stile ti sembri più leggibile.
Rajul,

7
Vorrei anche raccomandare di cambiare il nome del campo da "abilitato" a "swipePageChangeEnabled" o qualcosa del genere. Un mese dopo aver scritto il codice difficilmente ricorderai cosa significa "abilitato", specialmente quando la tua classe si chiama "CustomViewPager", dove non è chiaro quale sia la personalizzazione. Anche questa è una questione di stile, ma lo stile è importante se non vuoi finire con un progetto insopportabile, è più facile riscrivere completamente che risolverlo.
bytefu,

4
Dove posso chiamare setPagingEnabled? ._.
Ntikki,

107

Il modo più semplice è setOnTouchListenere tornare truea ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });

53
A volte non funziona. Sto usando un ViewPager con un FragmentPagerAdapter e diversi frammenti. Dopo aver impostato OnTouchListener su cercapersone, se lancio a sinistra, l'interfaccia utente si sposterà ancora a sinistra un po '.
Chris.Zou,

16
Funziona quando lo aggiungi pager.setCurrentItem(pager.getCurrentItem());prima di tornare true.
dng,

1
ha funzionato per me prima. non ho idea del perché non funzioni più bene.
sviluppatore Android

Sembra funzionare per me. Per risolvere alcuni problemi di layout che ho public int getItemPosition(Object object) { return POSITION_NONE; }nel mio adattatore, che forza la ricreazione delle pagine e forse risolve anche altri problemi.
r-hold

6
Questa è una soluzione parzialmente funzionante. I passaggi orizzontali vengono gestiti in un modo strano. Ho provato questo con un Drag'n Drop Gridview come parte di un ViewPager. Quando si trascina utilizzando questa soluzione, il trascinamento da sinistra a destra e da destra a sinistra non riesce. Personalmente trovo che l'approccio di Rajul sia il migliore.
Ton Snoei,

58

Meglio dichiararlo stilizzato, quindi puoi cambiarne la proprietà da xml:

private boolean swipeable;

public MyViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyViewPager);
    try {
        swipeable = a.getBoolean(R.styleable.MyViewPager_swipeable, true);
    } finally {
        a.recycle();
    }
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return swipeable ? super.onInterceptTouchEvent(event) : false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return swipeable ? super.onTouchEvent(event) : false;
}

E nei tuoi valori / attr.xml:

<declare-styleable name="MyViewPager">
  <attr name="swipeable" format="boolean" />
</declare-styleable>

in modo che tu possa usarlo nel tuo layout xml:

<mypackage.MyViewPager
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:swipeable="false" />

Ovviamente, puoi comunque avere una proprietà get / set.


58

Sovrascrivere solo onTouchEventeonInterceptTouchEvent non è sufficiente nel caso in cui ViewPager stesso sia contenuto in un altro ViewPager. Il ViewPager figlio ruberebbe gli eventi di tocco di scorrimento orizzontale dal ViewPager principale a meno che non sia posizionato sulla sua prima / ultima pagina.

Per far funzionare correttamente questa configurazione è necessario sostituire anche il canScrollHorizontallymetodo.

Vedi l' LockableViewPagerimplementazione di seguito.

public class LockableViewPager extends ViewPager {

    private boolean swipeLocked;

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

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

    public boolean getSwipeLocked() {
        return swipeLocked;
    }

    public void setSwipeLocked(boolean swipeLocked) {
        this.swipeLocked = swipeLocked;
    }

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

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

    @Override
    public boolean canScrollHorizontally(int direction) {
        return !swipeLocked && super.canScrollHorizontally(direction);
    }

}

3
Grazie, questo funziona molto bene su un ViewPager all'interno di un altro ViewPager.
Fernanda Bari,

1
Questo funziona per me, anche per un ViewPager all'interno di un altro ViewPager. La soluzione corretta non ha funzionato per me in quel caso.
Rafael Ruiz Muñoz,

arresta anche l'animazione quando viene utilizzata nelle schede.
Rishabh Srivastava,

Se lo disabilito e suppongo di volerlo abilitare, allora dove posso ottenere l'evento per chiamare setSwipeLocked (false)?
Ravi Yadav,

58

Ora non è necessario creare personalizzazioni ViewPager

Un nuovo ViewPager2 nome Visualizza disponibile in Android

Supporto per orientamento verticale

  • ViewPager2supporta il paging verticale oltre al tradizionale paging orizzontale. È possibile abilitare il paging verticale per un ViewPager2elemento impostandone l' android:orientationattributo

Utilizzando XML

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

Usando il codice

Per disabilitare lo scorrimento in viewpager2uso

viewPager2.setUserInputEnabled(false);

Per abilitare lo scorrimento in viewpager2uso

viewPager2.setUserInputEnabled(true);

per maggiori informazioni controlla questo

AGGIORNARE


3
È fantastico, ma sembra ancora incompleto. L'ho provato con 5 diversi frammenti e dopo il passaggio tra le pagine uno dei frammenti è stato perso, cioè la vista non è stata né ripristinata né gonfiata nuovamente
Toochka

@Toochka mi dispiace sapere che per me funziona benissimo puoi trovare il codice di lavoro di esempio da qui stackoverflow.com/a/54643817/7666442 se possibile per favore condividi il tuo codice
Nilesh Rathod

1
Ho potuto disabilitare con successo lo scorrimento su un ViewPager2 usando questo metodo
voghDev

1
@voghDev felice di saperlo
Nilesh Rathod

1
@PhaniRithvij si prega di controllare questa risposta stackoverflow.com/a/54643817/7666442 ho aggiunto tutti i dettagli come utilizzare viewpager2conRecyclerView.Adapter
Nilesh Rathod

35

Se si sta estendendo da ViewPager, è necessario anche eseguireexecuteKeyEvent l' override come indicato in precedenza da @araks

@Override
public boolean executeKeyEvent(KeyEvent event)
{
    return isPagingEnabled ? super.executeKeyEvent(event) : false;
}

Perché alcuni dispositivi come Galaxy Tab 4 10 'mostrano questi pulsanti in cui la maggior parte dei dispositivi non li mostra mai:

Pulsanti della tastiera


50
Samsung ha sempre rovinato tutto per gli sviluppatori Android.
toobsco42,

2
@ toobsco42 Samsung non è il solo in questo caso. SwiftKey (popolare app per tastiera) consente agli utenti di mettere le frecce sulla tastiera.
Sufian,

1
Questa è anche la soluzione se si desidera impedire a qualcuno che utilizza una tastiera / trackerball di effettuare il paging del proprio cercapersone.
se22as

28

Per disabilitare lo scorrimento

mViewPager.beginFakeDrag();

Per abilitare lo scorrimento

mViewPager.endFakeDrag();

22
Non è una buona soluzione perché consente piccole porzioni di movimento, almeno nella mia app.
koras,

Funziona bene per me. Quali sono gli svantaggi rispetto alle altre soluzioni fornite?
userM1433372

13

Avevo bisogno di disabilitare lo scorrimento su una pagina specifica e dargli una bella animazione con elastico, ecco come:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrolled(int position, float positionOffset,
                                   int positionOffsetPixels) {
            if (position == MANDATORY_PAGE_LOCATION && positionOffset > 0.5) {
                mViewPager.setCurrentItem(MANDATORY_PAGE_LOCATION, true);
            }
        }

Attende che la pagina successiva sia parzialmente visibile. onPageSelectedVerrà eseguito un codice per la pagina successiva in . Anche la pagina successiva cambierà. Quindi, questo codice non è necessario.
CoolMind,

13

So che è molto tardi per pubblicare questo post, ma ecco un piccolo trucco per raggiungere il tuo risultato;)

Aggiungi semplicemente una vista fittizia sotto il tuo viewpager:

<android.support.v4.view.ViewPager
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

<RelativeLayout
     android:id="@+id/dummyView"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</RelativeLayout>

Quindi aggiungi a OnClickListeneral tuo RelativeLayout.

dummyView = (RelativeLayout) findViewById(R.id.dummyView);

dummyView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         //Just leave this empty
    }
});

Diventa un po 'creativo con i layout, i loro posizionamenti e il loro comportamento e imparerai a trovare un modo per fare assolutamente tutto ciò che immagini :)

In bocca al lupo!


Un modo più semplice è utilizzare setClickableinvece di setOnClickListener, se non è necessario gestire l' onClickevento.
Caos,

questo non bloccherebbe anche i tocchi all'interno del viewpager?
sviluppatore Android

Si lo farà. È il comportamento previsto richiesto dall'OP @androiddeveloper
Dinuka Jay

@RickGrimesTheCoder Non credo che tu abbia capito la mia domanda. Intendo viste all'interno dei frammenti del viewpager. Saranno ancora tangibili?
sviluppatore Android

No, non lo saranno poiché il viewpager stesso ha un listener di clic. Questo è adatto solo per i casi in cui non hai elementi interattivi all'interno dei frammenti. Ad esempio un Welcome ViewPager che modifica dinamicamente i suoi frammenti @androiddeveloper
Dinuka Jay,

12

Ho scritto un CustomViewPagercon un controllo di scorrimento:

public class ScrollableViewPager extends ViewPager {
    private boolean canScroll = true;
    public ScrollableViewPager(Context context) {
        super(context);
    }
    public ScrollableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setCanScroll(boolean canScroll) {
        this.canScroll = canScroll;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return canScroll && super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return canScroll && super.onInterceptTouchEvent(ev);
    }
}

Se si imposta canScrollsu true, questo ViewPagerpuò essere scorrere con il dito, falseal contrario.

Lo uso nel mio progetto e funziona benissimo fino ad ora.


1
Cosa succede se ho un pulsante all'interno di ViewPager e voglio il clic? questa soluzione impedisce di fare clic su tutto ciò che si trova sotto viewpager.
aimiliano

6

Ho usato questa classe con successo. È necessario eseguire l'override di executeKeyEvent per evitare lo scorrimento con le frecce in alcuni dispositivi o per l'accessibilità:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class ViewPagerNoSwipe extends ViewPager {
    /**
     * Is swipe enabled
     */
    private boolean enabled;

    public ViewPagerNoSwipe(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = false; // By default swiping is disabled
    }

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

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

    @Override
    public boolean executeKeyEvent(KeyEvent event) {
        return this.enabled ? super.executeKeyEvent(event) : false;
    }

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

}

E nel file XML chiamalo così:

<package.path.ViewPagerNoSwipe
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Funziona. Solo lo scorrimento è disabilitato e il clic su una scheda è abilitato. AS avverte che il performClick()metodo non è ignorato.
CoolMind

5

In Kotlin, la mia soluzione, combinando le risposte sopra.

class CustomViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    var swipeEnabled = false

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onTouchEvent(ev) else false
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onInterceptTouchEvent(ev) else false
    }

    override fun executeKeyEvent(event: KeyEvent): Boolean {
        return if (swipeEnabled) super.executeKeyEvent(event) else false
    }
}

La sostituzione onInterceptTouchEvent()impedirà alle visualizzazioni figlio di ricevere input. Nella maggior parte dei casi questo non è il comportamento previsto.
Alex Semeniuk,

Sono stato in grado di interagire con le visualizzazioni figlio di ciascun frammento. Non sono sicuro di cosa ti riferisci.
Jeff Padgett,

5

In kotlin, possiamo risolverlo creando un widget personalizzato che eredita la classe ViewPager e aggiungendo un valore flag per controllare il comportamento dello scorrimento.

NoSwipePager.kt

class NoSwipePager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    var pagingEnabled: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onTouchEvent(event)
        } else false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onInterceptTouchEvent(event)
        } else false
    }
}

In XML

<your.package.NoSwipePager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/tab_layout" />

Disabilita lo scorrimento a livello di codice. Se il kotlin-android-extensionsplug-in viene applicato in build.gradle , lo scorrimento può essere disabilitato scrivendo il codice seguente.

view_pager.pagingEnabled = false

Altrimenti possiamo disabilitare lo scorrimento usando il codice qui sotto:

val viewPager : ViewPager = findViewById(R.id.view_pager)
viewPager.pagingEnabled = false

La sostituzione onInterceptTouchEvent()impedirà alle visualizzazioni figlio di ricevere input. Nella maggior parte dei casi questo non è il comportamento previsto.
Alex Semeniuk,

@AlexSemeniuk Hai riscontrato qualche problema dopo aver implementato questo? Avevo abilitato lo scorrimento degli elementi della vista del riciclatore per alcune azioni e funziona perfettamente. Quindi l'implementazione sta funzionando bene nel mio caso.
Sagar Chapagain,

Sagar Chapagain: o certo, l'ho fatto. Ciascuna delle mie pagine contiene una vista personalizzata, che elabora i tocchi in vari modi (inclusi scorrimento, trascinamento, tocchi singoli e lunghi). Non chiamare i super.onInterceptTouchEvent(event)risultati in queste viste senza ricevere alcun input (che è lo scopo documentato del onInterceptTouchEventmetodo).
Alex Semeniuk,

In tal caso, è preferibile utilizzare il frammento figlio e mantenere il backstack.
Sagar Chapagain,

In che modo ciò è rilevante per la domanda attuale? I frammenti sono collocati all'interno di alcuni contenitori (che sono Viste ) e il loro layout contiene Viste . Indipendentemente dal contenuto che ho all'interno di ViewPager, mi sto ancora occupando del fatto che il onInterceptTouchEvent()metodo di override impedisce che (contenuto) riceva input.
Alex Semeniuk,


1

Un'altra soluzione semplice per disabilitare lo scorrimento su una pagina specifica (in questo esempio, pagina 2):

int PAGE = 2;
viewPager.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
        if (viewPager.getCurrentItem() == PAGE) {
                viewPager.setCurrentItem(PAGE-1, false);
                viewPager.setCurrentItem(PAGE, false);
                return  true;
        }
        return false;
}

1
This worked for me

viewPager.setOnTouchListener(new View.OnTouchListener() {
                                         @Override
                                         public boolean onTouch(View v, MotionEvent event) {
                                             if (viewPager.getCurrentItem() == 0) {
                                                 viewPager.setCurrentItem(-1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 1) {
                                                 viewPager.setCurrentItem(1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 2) {
                                                 viewPager.setCurrentItem(2, false);
                                                 return true;
                                             }
                                             return true;
                                         }
                                     });

1

Se scrivi una galleria di immagini con ImageViews e ViewPager, che supporta zoom e pan, vedi una soluzione semplice descritta qui: Implementazione di ImageView zoomabile estendendo il ViewPager predefinito in Phimpme Android (e esempio Github - PhotoView ). Questa soluzione non funziona da ViewPagersola.

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

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        try {
            return super.onInterceptTouchEvent(event);
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

1

Se stai usando ViewPager2 devi solo usare:

viewpager.setUserInputEnabled(false);

Dai documenti :

Abilita o disabilita lo scorrimento avviato dall'utente. Ciò include input touch (gesti di scorrimento e di lancio) e input di accessibilità. La disabilitazione dell'input da tastiera non è ancora supportata. Quando lo scorrimento avviato dall'utente è disabilitato, gli scorrevoli programmatici attraverso setCurrentItem continuano a funzionare. Per impostazione predefinita, lo scorrimento avviato dall'utente è abilitato.

Grazie a: https://stackoverflow.com/a/61685871/9026710


0

Se vuoi implementare lo stesso per Android in Xamarin, ecco una traduzione in C #

Ho scelto di nominare l'attributo " ScrollEnabled ". Perché iOS utilizza solo lo stesso nome excat. Quindi, hai la stessa denominazione su entrambe le piattaforme, rende più facile per gli sviluppatori.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Android.Util;

namespace YourNameSpace.ViewPackage {

    // Need to disable swiping for ViewPager, if user performs Pre DSA and the dsa is not completed yet
    // http://stackoverflow.com/questions/9650265/how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-s
    public class CustomViewPager: ViewPager {
        public bool ScrollEnabled;

        public CustomViewPager(Context context, IAttributeSet attrs) : base(context, attrs) {
            this.ScrollEnabled = true;
        }

        public override bool OnTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnTouchEvent(e);
            }
            return false;
        }

        public override bool OnInterceptTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnInterceptTouchEvent(e);
            }
            return false;
        }

        // For ViewPager inside another ViewPager
        public override bool CanScrollHorizontally(int direction) {
            return this.ScrollEnabled && base.CanScrollHorizontally(direction);
        }

        // Some devices like the Galaxy Tab 4 10' show swipe buttons where most devices never show them
        // So, you could still swipe through the ViewPager with your keyboard keys
        public override bool ExecuteKeyEvent(KeyEvent evt) {
            return this.ScrollEnabled ? base.ExecuteKeyEvent(evt) : false;
        }
    }
}

Nel file .axml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <YourNameSpace.ViewPackage.CustomViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/white"
      android:layout_alignParentTop="true" />
</LinearLayout>

0

Nessuno dei codici sopra funziona senza problemi. Ho provato questo

<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/pager"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                </HorizontalScrollView>

0

ecco la mia implementazione
che se si desidera disabilitare l'animazione di scorrimento, è possibile utilizzare l'ascensore di scorrimento a destra e sinistra e si desidera comunque scorrere con le dita ma senza animazione

ViewpagerMetodo 1-Override onInterceptTouchEventeonTouchEvent

2- creane uno tuo GestureDetector

3- rilevare il gesto di scorrimento e utilizzare il setCurrentItem(item, false)

ViewPager

public class ViewPagerNoSwipe extends ViewPager {
    private final GestureDetector gestureDetector;
    private OnSwipeListener mOnSwipeListener;

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        mOnSwipeListener = onSwipeListener;
    }

    public ViewPagerNoSwipe(@NonNull Context context) {
        super(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

    }

    public ViewPagerNoSwipe(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GestureListener());


    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        return false;
    }

    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeRight();
                        } else {
                            if(mOnSwipeListener!=null)
                                mOnSwipeListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeBottom();
                    } else {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public interface OnSwipeListener {

         void onSwipeRight();

        void onSwipeLeft();

        void onSwipeTop();

        void onSwipeBottom();
    }
}

quando si configura ViewPager impostare swipeListener

postsPager.setOnSwipeListener(new ViewPagerNoSwipe.OnSwipeListener() {
            @Override
            public void onSwipeRight() {

              postsPager.setCurrentItem(postsPager.getCurrentItem() + 1,false);

            }

            @Override
            public void onSwipeLeft() {

            postsPager.setCurrentItem(postsPager.getCurrentItem() - 1, false);

            }
             ...
           }

0

Ho appena personalizzato un po 'il viewpager e disabilito facilmente lo scorrimento.

public class CustomViewPager extends ViewPager {

private boolean swipeLocked;

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

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

public boolean getSwipeLocked() {
    return swipeLocked;
}

public void setSwipeLocked(boolean swipeLocked) {
    this.swipeLocked = swipeLocked;
}

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

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

@Override
public boolean canScrollHorizontally(int direction) {
    return !swipeLocked && super.canScrollHorizontally(direction);
}
}

-1
shareViewPager?.setOnTouchListener(object :View.OnTouchListener{
            override fun onTouch(v: View?, event: MotionEvent?): Boolean {
                for (PAGE in 0..shareViewPager.adapter!!.count){
                    if (shareViewPager.currentItem==PAGE){
                        shareViewPager.setCurrentItem(PAGE-1,false)
                        shareViewPager.setCurrentItem(PAGE,false)
                    }}
                return true
            }

        })
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.