it-swarm.com.de

Wie können Sie das Paging durch Wischen mit dem Finger in ViewPager deaktivieren, aber dennoch programmgesteuert wischen können?

Ich habe ViewPager und darunter 10 Tasten. Durch Klicken auf die Schaltfläche, zum Beispiel # 4, geht der Pager um Seite 4 von mPager.setCurrentItem(3);. Ich möchte das Paging jedoch deaktivieren, indem ich mit dem Finger horizontal streichen sollte. Das Paging erfolgt alsoONLYdurch Anklicken der Schaltflächen. Also, wie kann ich das Wischen mit dem Finger deaktivieren?

461
theateist

Sie müssen ViewPager subclass. onTouchEvent hat viele gute Dinge, die Sie nicht ändern möchten, z. B., dass untergeordnete Ansichten Berührungen erhalten sollen. onInterceptTouchEvent möchten Sie ändern. Wenn Sie sich den Code für ViewPager ansehen, 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 src-Ordner 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 Sie als Nächstes sicher, dass Sie diese Klasse anstelle der regulären ViewPager verwenden, die Sie wahrscheinlich als Android.support.v4.view.ViewPager angegeben haben. 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 einer LinearLayout und soll den gesamten Bildschirm einnehmen, weshalb layout_weight 1 ist und layout_height 0dp ist.

UndsetMyScroller();Methode sorgt für einen reibungslosen Übergang

813
louielouie

Die allgemeinere Erweiterung von ViewPager würde darin bestehen, eine SetPagingEnabled-Methode zu erstellen, damit wir das Paging im laufenden Betrieb aktivieren und deaktivieren können .. Um das Swiping zu aktivieren/deaktivieren, überschreiben Sie einfach zwei Methoden: onTouchEvent und 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 diese Option 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 setPagingEnabled-Methode mit false aufrufen, und die Benutzer können nicht zur Paginierung wechseln.

432
Rajul

Der einfachste Weg ist, setOnTouchListener und true für ViewPager zurückzugeben.

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

Besser, es als stylable zu deklarieren, so dass Sie seine Eigenschaften von XML ä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 deinen Werten/attr.xml:

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

damit Sie es in Ihrem Layout-XML verwenden können:

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

53
Pietro

Nur das Überschreiben von onTouchEvent und onInterceptTouchEvent reicht nicht aus, wenn Sie ViewPager selbst in einem anderen ViewPager verwenden. Child ViewPager stiehlt horizontale Scroll-Berührungsereignisse vom übergeordneten ViewPager, sofern es nicht auf der ersten/letzten Seite positioniert ist.

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

Siehe LockableViewPager-Implementierung weiter 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);
    }

}
45
sidon

Wischen deaktivieren 

mViewPager.beginFakeDrag();

Wischen aktivieren 

mViewPager.endFakeDrag();
28
KAMAL VERMA

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

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

Da einige Geräte wie das Galaxy Tab 4 10 'diese Schaltflächen anzeigen, werden sie von den meisten Geräten nie angezeigt:

 Keyboard buttons

25
Grease

Ich musste das Wischen auf einer bestimmten Seite deaktivieren und ihm eine Nice-Rubberband-Animation geben.

    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);
            }
        }
14
Oded Breiner

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

Fügen Sie einfach eine Dummy-Ansicht unten Ihren 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 eine OnClickListener zu Ihrer RelativeLayout hinzu.

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

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

Machen Sie sich mit Layouts, ihren Platzierungen und ihrem Verhalten ein bisschen kreativer und Sie werden einen Weg finden, absolut alles zu tun, was Sie sich vorstellen :)

Viel Glück!

11
Dinuka

Ich habe eine CustomViewPager mit einer Swip-Steuerung geschrieben:

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 canScroll auf true setzen, kann diese ViewPager mit dem Finger wischen, im Gegenteil false.

Ich verwende das in meinem Projekt, und es funktioniert bis jetzt großartig.

10
L. Swifter

Versuchen Sie es mit onInterceptTouchEvent () und/oder onTouchEvent () zu überschreiben und true zurückzugeben, wodurch Berührungsereignisse im Pager verarbeitet werden.

4
AdamK

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 Wischverhaltens 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-extensions -Plugin 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 folgendem Code deaktivieren:

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

Jetzt müssen wir keine benutzerdefinierten ViewPager erstellen

Eine neue ViewPager2 name-Ansicht in Android verfügbar

Zum Deaktivieren des Wischens in viewpager2 verwenden Sie

viewPager2.setUserInputEnabled(false);

So aktivieren Sie das Wischen in viewpager2 Use

viewPager2.setUserInputEnabled(true);

weitere Informationen finden Sie hier

3
Nilesh Rathod

Ich habe diese Klasse mit Erfolg benutzt. Das Überschreiben von executeKeyEvent ist erforderlich, um das Wischen mit Pfeilen in einigen Geräten oder die Zugänglichkeit 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 nenne es so:

<package.path.ViewPagerNoSwipe
    Android:layout_width="match_parent"
    Android:layout_height="match_parent" />
2
madx

Wenn Sie eine Bildergalerie mit ImageViews und ViewPager schreiben, die Zoom und Pan 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 sample - PhotoView ). Diese Lösung funktioniert nicht nur mit ViewPager.

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
CoolMind

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 die gleiche Benennung verwendet. Sie haben also auf beiden Plattformen die gleiche Benennung und machen es für Entwickler einfacher.

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 .axml-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>
1
Lepidopteron

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

Ich habe den Viewer nur ein wenig angepasst und das Wischen leicht 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);
}
}
0
Shivam Yadav

hier ist meine umsetzung
Wenn Sie die Swipe-Animation deaktivieren möchten, können Sie den swipeListener links und rechts verwenden und trotzdem den Bildlauf per Finger, jedoch ohne Animation, durchführen 

1-Überschreibung Viewpager Methode onInterceptTouchEvent und onTouchEvent 

2- Erstellen Sie Ihre eigene 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, legen Sie den SwipeListener fest 

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
tamtom

In Kotlin meine Lösung, obige Antworten kombinierend.

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
    }
}
0
Jeff Padgett
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;
                                         }
                                     });
0

Keiner der oben genannten Codes funktioniert reibungslos. Ich habe es 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
Nandan Singh