Wie deaktiviere ich das Paging, indem ich in ViewPager mit dem Finger wische, aber trotzdem programmgesteuert wischen kann?


550

Ich habe ViewPager und darunter habe ich 10 Schaltflächen. Durch Klicken auf die Schaltfläche, z. B. Nr. 4, wechselt der Pager sofort zu Seite Nr. 4 von mPager.setCurrentItem(3);. Ich möchte das Paging jedoch deaktivieren, indem ich mit dem Finger horizontal wische. Das Paging erfolgt also NUR durch Klicken auf die Schaltflächen. Wie kann ich das Wischen mit dem Finger deaktivieren?


Wie wäre es überhaupt mit ViewFlipper ? Es erspart Ihnen viel Kopfschmerzen.
Alex Semeniuk

Antworten:


885

Sie müssen eine Unterklasse bilden ViewPager. onTouchEventEs enthält viele gute Dinge, die Sie nicht ändern möchten, z. B. das Zulassen, dass untergeordnete Ansichten berührt werden. onInterceptTouchEventist das, was du ändern willst. Wenn Sie sich den Code für ansehen ViewPager, sehen Sie den Kommentar:

    /*
     * 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.
     */

Hier ist eine Komplettlösung:

Fügen Sie diese Klasse zunächst Ihrem srcOrdner hinzu:

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

Stellen ViewPagerSie als Nächstes sicher, dass Sie diese Klasse anstelle der regulären Klasse verwenden , die Sie wahrscheinlich als angegeben haben android.support.v4.view.ViewPager. In Ihrer Layoutdatei möchten Sie Folgendes angeben:

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

Dieses spezielle Beispiel befindet sich in a LinearLayoutund soll den gesamten Bildschirm einnehmen, weshalb layout_weight1 und layout_height0 dp ist.

Und setMyScroller();Methode ist für einen reibungslosen Übergang


3
@louielouie Nebenbei bemerkt: Gibt es einen bestimmten Grund, warum Sie die Lösung für 0dpGröße / 1Gewicht anstelle von match_parentHöhe gewählt haben, um den Vollbildeffekt zu erzielen? Erzielen Sie dadurch Leistungsverbesserungen?
Ubuntudroid

29
Diese Antwort verhindert nicht das Wischen von Seiten, wenn Sie die linke / rechte Tastaturtaste verwenden (versuchen Sie es im Emulator). Möglicherweise kein Problem für Touch-Geräte, bei Fernsehgeräten und Laptops jedoch möglicherweise.
Vincent Mimoun-Prat

8
@MarvinLabs @Thorbear Der richtige Weg, um den Bildlauf über die Tastatur zu deaktivieren, besteht darin, das zu überschreiben executeKeyEvent(). Dies ist die Methode, die dann aufgerufen wird allowScroll(). // Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
Araks

6
Nun, dies deaktiviert auch das vertikale Scrollen ... das ist schlecht, wenn Sie Listenansichten verwenden.
Mai

5
Ich hoffe, Google hätte gerade eine Methode bereitstellen können, mit der wir unsere Schnittstellenmethode für den Umgang mit Berührungen / Wischen bereitstellen, weil ich glaube, dass dies nicht schaden würde.
Neon Warge

466

Die allgemeinere Erweiterung von ViewPagerwäre, eine SetPagingEnabledMethode zu erstellen , mit der wir Paging im laufenden Betrieb aktivieren und deaktivieren können. Um das Wischen zu aktivieren / deaktivieren, überschreiben Sie einfach zwei Methoden: onTouchEventund onInterceptTouchEvent. Beide geben "false" zurück, wenn das Paging deaktiviert wurde.

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

Wählen Sie dann diesen anstelle des in XML integrierten Viewpagers aus

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

Sie müssen nur die setPagingEnabledMethode mit aufrufen , falseund Benutzer können nicht zum Paginieren wischen.


3
Funktioniert perfekt für eine Ansicht mit mehreren Unteransichten, in denen horizontales Scrollen verwendet wird (z. B. AChartEngine-Diagramm). In meinem Fragment verwende ich einen Rückruf für meine Aktivität, der anzeigt, dass das Paging deaktiviert oder deaktiviert werden soll, je nachdem, ob der Benutzer das Diagramm berührt (ACTION_MOVE) oder verlassen hat (ACTION_CANCEL). Vielen Dank!
Riper

32
Sie können Ihre onTouchEventund onInterceptTouchEventMethoden mitreturn enabled && super.onTouchEvent(event);
nbarraille

2
@nbarraille das ist nur eine Frage des Stils. Sie können jeden Stil verwenden, der Ihnen besser lesbar erscheint.
Rajul

7
Ich würde auch empfehlen, den Namen des Feldes von "enabled" in "swipePageChangeEnabled" oder ähnliches zu ändern. Einen Monat nach dem Schreiben des Codes werden Sie sich kaum daran erinnern, was "aktiviert" bedeutet, insbesondere wenn Ihre Klasse "CustomViewPager" heißt und nicht klar ist, um welche Anpassung es sich handelt. Das ist auch eine Frage des Stils, aber Stil ist wichtig, wenn Sie nicht mit einem nicht unterstützbaren Projekt enden möchten. Es ist einfacher, es vollständig neu zu schreiben, als es zu reparieren.
Bytefu

4
Wo rufe ich setPagingEnabled auf? ._.
Ntikki

107

Der einfachste Weg ist zu setOnTouchListenerund zurück truefür ViewPager.

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

53
Funktioniert manchmal nicht. Ich verwende einen ViewPager mit einem FragmentPagerAdapter und mehreren Fragmenten. Wenn ich nach dem Setzen von OnTouchListener auf Pager nach links fliege, bewegt sich die Benutzeroberfläche immer noch ein wenig nach links.
Chris.Zou

16
Es funktioniert, wenn Sie pager.setCurrentItem(pager.getCurrentItem());vor der Rückkehr hinzufügen true.
dng

1
es hat bei mir schon mal geklappt. Keine Ahnung, warum es nicht mehr gut funktioniert.
Android-Entwickler

scheint für mich zu arbeiten. Um einige Layoutfehler zu beheben, die ich public int getItemPosition(Object object) { return POSITION_NONE; }in meinem Adapter habe, wird die Neuerstellung von Seiten erzwungen und möglicherweise auch andere Probleme gelöst.
R-Hold

6
Dies ist eine teilweise funktionierende Lösung. Horizontale Wischbewegungen werden auf seltsame Weise gehandhabt. Ich habe dies mit einem Drag'n Drop Gridview als Teil eines ViewPagers getestet. Beim Ziehen mit dieser Lösung schlägt das Ziehen von links nach rechts und von rechts nach links fehl. Persönlich finde ich Rajuls Ansatz am besten.
Ton Snoei

58

Es ist besser, es als stilbar zu deklarieren, damit Sie seine Eigenschaft von xml aus ändern können:

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

Und in Ihren Werten / attr.xml:

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

damit du es in deinem Layout xml verwenden kannst:

<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" />

Natürlich können Sie immer noch eine get / set-Eigenschaft haben.


58

Überschreiben nur onTouchEventund onInterceptTouchEventist nicht ausreichend, wenn Sie ViewPager selbst in einem anderen ViewPager haben. Der untergeordnete ViewPager stiehlt dem übergeordneten ViewPager horizontale Scroll-Touch-Ereignisse, es sei denn, er befindet sich auf der ersten / letzten Seite.

Damit dieses Setup ordnungsgemäß funktioniert, müssen Sie auch die canScrollHorizontallyMethode überschreiben .

Siehe LockableViewPagerImplementierung unten.

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
Vielen Dank, dies funktioniert sehr gut auf einem ViewPager in einem anderen ViewPager.
Fernanda Bari

1
Dies funktioniert für mich auch für einen ViewPager in einem anderen ViewPager. Die richtige Lösung hat in diesem Fall bei mir nicht funktioniert.
Rafael Ruiz Muñoz

Stoppt auch die Animation, wenn sie in Registerkarten verwendet wird.
Rishabh Srivastava

Wenn ich es deaktiviere und annehme, dass ich es aktivieren möchte, wo kann ich dann das Ereignis dazu bringen, setSwipeLocked (false) aufzurufen?
Ravi Yadav

57

Jetzt müssen wir keine benutzerdefinierten erstellen ViewPager

Ein neuer ViewPager2 Name Ansicht in Android verfügbar

Unterstützung für vertikale Ausrichtung

  • ViewPager2unterstützt vertikales Paging zusätzlich zum herkömmlichen horizontalen Paging. Sie können das vertikale Paging für ein ViewPager2Element aktivieren, indem Sie dessen android:orientationAttribut festlegen

Verwenden von XML

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

Code verwenden

Deaktivieren des Wischens während der viewpager2Verwendung

viewPager2.setUserInputEnabled(false);

So aktivieren Sie das Wischen in " viewpager2Verwendung"

viewPager2.setUserInputEnabled(true);

Weitere Informationen finden Sie hier

AKTUALISIEREN


3
Es ist großartig, scheint aber immer noch unvollständig zu sein. Ich habe es mit 5 verschiedenen Fragmenten ausprobiert und nach dem Wechseln zwischen den Seiten ging eines der Fragmente irgendwie verloren, dh die Ansicht wurde weder wiederhergestellt noch wieder aufgeblasen
Toochka

@ Toochka Entschuldigung zu hören, dass es für mich gut funktioniert. Den Beispiel- Arbeitscode finden Sie hier. Stackoverflow.com/a/54643817/7666442 Wenn möglich, teilen Sie
uns

1
Ich konnte das Wischen auf einem ViewPager2 mit dieser Methode erfolgreich deaktivieren
voghDev

1
@voghDev freut sich das zu hören
Nilesh Rathod

1
@PhaniRithvij Bitte überprüfen Sie diese Antwort stackoverflow.com/a/54643817/7666442 i Ich habe alle Details hinzugefügt, wie man viewpager2mitRecyclerView.Adapter
Nilesh Rathod

35

Wenn Sie von ViewPager aus erweitern, müssen Sie auch überschreiben,executeKeyEvent wie zuvor von @araks angegeben

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

Weil einige Geräte wie das Galaxy Tab 4 10 'diese Schaltflächen dort anzeigen, wo die meisten Geräte sie nie anzeigen:

Tastaturtasten


50
Samsung vermasselt immer alles für Android-Entwickler.
toobsco42

2
@ toobsco42 Samsung ist in diesem Fall nicht allein. Mit SwiftKey (beliebte Tastatur-App) können Benutzer Pfeile auf ihre Tastaturen setzen.
Sufian

1
Dies ist auch die Lösung, wenn Sie verhindern möchten, dass jemand, der eine Tastatur / einen Trackerball verwendet, Ihren Pager anruft.
22. September

28

Swipe deaktivieren

mViewPager.beginFakeDrag();

Swipe aktivieren

mViewPager.endFakeDrag();

22
Es ist keine gute Lösung, da es zumindest in meiner App kleine Teile der Bewegung zulässt.
Koras

Funktioniert gut für mich. Was sind die Nachteile gegenüber den anderen angebotenen Lösungen?
userM1433372

13

Ich musste das Wischen auf einer bestimmten Seite deaktivieren und ihr eine schöne Gummibandanimation geben. So geht's:

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

Es wartet, bis die nächste Seite teilweise sichtbar ist. Ein Code für die nächste Seite onPageSelectedwird ausgeführt. Sogar die nächste Seite wird wechseln. Dieser Code wird also nicht benötigt.
CoolMind

13

Ich weiß, es ist mächtig spät, dies zu posten, aber hier ist ein kleiner Hack, um dein Ergebnis zu erzielen;)

Fügen Sie einfach eine Dummy-Ansicht unter Ihrem Viewpager hinzu:

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

Fügen Sie dann ein OnClickListenerzu Ihrem hinzu RelativeLayout.

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

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

Werden Sie ein bisschen kreativ mit Layouts, deren Platzierungen und ihrem Verhalten und Sie werden lernen, einen Weg zu finden, um absolut alles zu tun, was Sie sich vorstellen :)

Viel Glück!


Eine einfachere Möglichkeit ist die Verwendung setClickablevon setOnClickListener, wenn Sie das onClickEreignis nicht behandeln müssen .
Chaos

würde dies nicht auch Berührungen im Viewpager blockieren?
Android-Entwickler

Ja, es wird. Es ist das erwartete Verhalten von OP @androiddeveloper
Dinuka Jay

@ RickGrimesTheCoder Ich glaube nicht, dass du meine Frage verstanden hast. Ich meine Ansichten innerhalb der Fragmente des Viewpagers. Werden sie noch berührbar sein?
Android-Entwickler

Nein, das werden sie nicht, da der Viewpager selbst einen Klick-Listener hat. Dies ist nur für Fälle geeignet, in denen Sie keine interaktiven Elemente in den Fragmenten haben. Zum Beispiel ein Welcome ViewPager, der seine Fragmente dynamisch ändert @androiddeveloper
Dinuka Jay

12

Ich schrieb eine CustomViewPagermit einer Wischsteuerung:

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

Wenn Sie setzen canScrollauf true, dies ViewPagerkann mit dem Finger werden klauen, falseim Gegenteil.

Ich benutze dies in meinem Projekt und es funktioniert bis jetzt großartig.


1
Was ist, wenn ich eine Schaltfläche im ViewPager habe und den Klick möchte? Diese Lösung verhindert, dass alles unter dem Viewpager angeklickt wird.
aimiliano

6

Ich habe diese Klasse mit Erfolg genutzt. Das Überschreiben des executeKeyEvent ist erforderlich, um das Wischen mit Pfeilen auf einigen Geräten oder die Barrierefreiheit zu vermeiden:

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

}

Und in der XML nennen Sie es so:

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

Es klappt. Nur Wischen ist deaktiviert und das Klicken auf eine Registerkarte ist aktiviert. AS warnt davor, dass die performClick()Methode nicht überschrieben wird.
CoolMind

5

In Kotlin meine Lösung, die obigen Antworten kombiniert.

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

Durch das Überschreiben onInterceptTouchEvent()wird verhindert, dass untergeordnete Ansichten Eingaben erhalten. In den meisten Fällen ist dies nicht das beabsichtigte Verhalten.
Alex Semeniuk

Ich konnte mit untergeordneten Ansichten jedes Fragments interagieren. Nicht sicher, worauf Sie sich beziehen.
Jeff Padgett

5

In Kotlin können wir dieses Problem lösen, indem wir ein benutzerdefiniertes Widget erstellen, das die ViewPager-Klasse erbt, und einen Flag-Wert zum Steuern des Swipe-Verhaltens hinzufügen.

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" />

Deaktivieren Sie das Wischen programmgesteuert. Wenn das kotlin-android-extensionsPlugin in build.gradle angewendet wird , kann das Wischen durch Schreiben des folgenden Codes deaktiviert werden.

view_pager.pagingEnabled = false

Andernfalls können wir das Wischen mit dem folgenden Code deaktivieren:

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

Durch das Überschreiben onInterceptTouchEvent()wird verhindert, dass untergeordnete Ansichten Eingaben erhalten. In den meisten Fällen ist dies nicht das beabsichtigte Verhalten.
Alex Semeniuk

@AlexSemeniuk Hatten Sie nach der Implementierung ein Problem festgestellt? Ich habe das Wischen von Elementen in der Recycler-Ansicht für einige Aktionen aktiviert und es funktioniert einwandfrei. Die Implementierung funktioniert in meinem Fall also einwandfrei.
Sagar Chapagain

Sagar Chapagain: oder natürlich habe ich. Jede meiner Seiten enthält eine benutzerdefinierte Ansicht, die Berührungen auf verschiedene Arten verarbeitet (einschließlich Scrollen, Ziehen, einzelnes und langes Tippen). Wenn super.onInterceptTouchEvent(event)in diesen Ansichten keine Ergebnisse aufgerufen werden, werden keine Eingaben empfangen (dies ist der dokumentierte Zweck der onInterceptTouchEventMethode).
Alex Semeniuk

In diesem Fall sollten Sie lieber ein untergeordnetes Fragment verwenden und den Backstack beibehalten.
Sagar Chapagain

Wie ist das für die aktuelle Frage relevant? Fragmente werden in einigen Containern (die Ansichten sind ) platziert und ihr eigenes Layout enthält Ansichten . Unabhängig davon, welchen Inhalt ich im ViewPager habe, beschäftige ich mich immer noch mit der Tatsache, dass die überschreibende onInterceptTouchEvent()Methode verhindert, dass dieser (Inhalt) Eingaben empfängt.
Alex Semeniuk

4

Versuchen Sie, true von onInterceptTouchEvent () und / oder onTouchEvent () zu überschreiben und zurückzugeben , wodurch Berührungsereignisse auf dem Pager verbraucht werden.


1
würde er nicht zurückkehren wollen, um truezu implizieren, dass das Berührungsereignis behandelt wurde?
3.

1

Eine weitere einfache Lösung zum Deaktivieren des Wischens auf einer bestimmten Seite (in diesem Beispiel Seite 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

Wenn Sie eine Bildergalerie mit ImageViews und schreiben ViewPager, die Zoomen und Schwenken unterstützt, finden Sie eine einfache Lösung, die hier beschrieben wird: Implementieren einer zoombaren ImageView durch Erweitern des Standard-ViewPagers in Phimpme Android (und Github-Beispiel - PhotoView ). Diese Lösung funktioniert nicht ViewPageralleine.

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

Wenn Sie ViewPager2 verwenden, müssen Sie nur Folgendes verwenden:

viewpager.setUserInputEnabled(false);

Aus den Dokumenten :

Aktivieren oder deaktivieren Sie das vom Benutzer initiierte Scrollen. Dies umfasst Berührungseingaben (Scroll- und Fling-Gesten) und Eingabehilfen. Das Deaktivieren der Tastatureingabe wird noch nicht unterstützt. Wenn der vom Benutzer initiierte Bildlauf deaktiviert ist, funktionieren programmgesteuerte Bildläufe durch setCurrentItem weiterhin. Standardmäßig ist das vom Benutzer initiierte Scrollen aktiviert.

Vielen Dank an: https://stackoverflow.com/a/61685871/9026710


0

Wenn Sie dasselbe für Android in Xamarin implementieren möchten, finden Sie hier eine Übersetzung in C #

Ich habe das Attribut " ScrollEnabled " genannt. Weil iOS nur den gleichen Namen verwendet. Sie haben also auf beiden Plattformen die gleiche Benennung, was es Entwicklern einfacher macht.

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

In der XML-Datei:

<?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

Keiner der oben genannten Codes funktioniert reibungslos. Ich habe dies versucht

<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

Hier ist meine Implementierung
: Wenn Sie die Swipe-Animation deaktivieren möchten, können Sie den swipeListener links und rechts verwenden und möchten weiterhin mit dem Finger scrollen, jedoch ohne Animation

1-Override- ViewpagerMethode onInterceptTouchEventundonTouchEvent

2- Erstellen Sie Ihre eigenen GestureDetector

3- Erkennen Sie die Wischgeste und verwenden Sie die 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();
    }
}

Wenn Sie den ViewPager einrichten, stellen Sie den swipeListener ein

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

Ich habe den Viewpager nur ein wenig angepasst und das Wischen einfach deaktiviert.

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
            }

        })
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.