Jak wyłączyć stronicowanie, przesuwając palcem w ViewPager, ale nadal być w stanie przesuwać programowo?
Mam Viewpagera i pod nim mam 10 przycisków. Klikając na przycisk, na przykład #4, pager przechodzi natychmiast do strony #4 przez mPager.setCurrentItem(3);
. Ale chcę wyłączyć stronicowanie, przesuwając palcem w poziomie. Tak więc, stronicowanie odbywa się tylko klikając na przyciski.
Jak Mogę wyłączyć przesuwanie palcem?
17 answers
Musisz podklasować ViewPager. onTouchEvent ma w sobie wiele dobrych rzeczy, których nie chcesz zmieniać, takich jak umożliwienie widzeniom dziecięcym dotknięcia. onInterceptTouchEvent jest tym, co chcesz zmienić. Jeśli spojrzysz na kod Viewpagera, zobaczysz komentarz:
/*
* 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.
*/
Oto kompletne rozwiązanie:
Najpierw dodaj tę klasę do katalogu src:
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*/);
}
}
}
Następnie upewnij się, że używasz tej klasy zamiast zwykłego Viewpagera, który prawdopodobnie podałeś jako android.wsparcie.v4.widok.ViewPager. W pliku układu będziesz chciał go określić za pomocą czegoś w rodzaju:
<com.yourcompany.NonSwipeableViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
Ten konkretny przykład znajduje się w LinearLayout i ma zająć cały ekran, dlatego layout_weight wynosi 1, A layout_height 0DP.
I setMyScroller (); metoda służy do płynnego przejścia
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-17 04:52:24
Bardziej ogólnym rozszerzeniem ViewPager
byłoby stworzenie metody SetPagingEnabled
, abyśmy mogli włączać i wyłączać stronicowanie w locie.
Aby włączyć / wyłączyć przesuwanie, wystarczy przejrzeć dwie metody: onTouchEvent
i onInterceptTouchEvent
. Oba zwracają "false", jeśli stronicowanie zostało wyłączone.
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;
}
}
Następnie wybierz to zamiast wbudowanego viewpagera w XML
<mypackage.CustomViewPager
android:id="@+id/myViewPager"
android:layout_height="match_parent"
android:layout_width="match_parent" />
Wystarczy wywołać metodę setPagingEnabled
z false
i użytkownicy nie będą mogli przesunąć do paginate.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 18:51:37
Najprostszym sposobem jest setOnTouchListener
i zwrócenie true
dla ViewPager
.
mPager.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
return true;
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 12:45:46
Lepiej zadeklarować, że jest styleable, więc możesz zmienić jego właściwość z 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;
}
I w Twoich wartościach / attr.xml:
<declare-styleable name="MyViewPager">
<attr name="swipeable" format="boolean" />
</declare-styleable>
Aby można było go używać w układzie 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" />
Oczywiście nadal możesz mieć właściwość get / set.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-08 12:54:07
Nadpisywanie tylko onTouchEvent
i {[2] } nie jest wystarczające, jeśli masz Viewpagera wewnątrz innego Viewpagera. ViewPager potomny wykradałby poziome zdarzenia dotykowe przewijania z nadrzędnego Viewpagera, chyba że jest umieszczony na pierwszej / ostatniej stronie.
Aby ta konfiguracja działała poprawnie, musisz nadpisać również metodę canScrollHorizontally
.
Patrz LockableViewPager
implementacja poniżej.
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 09:22:21
Aby wyłączyć machnięcie
mViewPager.beginFakeDrag();
Aby włączyć przesunięcie
mViewPager.endFakeDrag();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 12:45:22
Jeśli rozszerzasz z ViewPager, musisz również nadpisać executeKeyEvent
Jak wskazano wcześniej przez @araks
@Override
public boolean executeKeyEvent(KeyEvent event)
{
return isPagingEnabled ? super.executeKeyEvent(event) : false;
}
Ponieważ niektóre urządzenia, takie jak Galaxy Tab 4 10 ' pokazują te przyciski, gdzie większość urządzeń nigdy ich nie pokazuje:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-01 18:16:29
Musiałem wyłączyć przesuwanie na jednej konkretnej stronie i dać jej ładną gumową animację, oto jak:
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-26 21:07:28
Wiem, że jest bardzo późno, aby to opublikować, ale tutaj jest mały hack, aby osiągnąć swój wynik;)
Po prostu dodaj fałszywy Widok poniżej swojego viewpagera:
<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>
Następnie dodaj OnClickListener
do swojego RelativeLayout
.
dummyView = (RelativeLayout) findViewById(R.id.dummyView);
dummyView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Just leave this empty
}
});
Bądź trochę kreatywny z layoutami, ich rozmieszczeniem i zachowaniem, a nauczysz się znaleźć sposób na absolutnie wszystko, co sobie wyobrażasz :)
Powodzenia!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 12:45:07
Napisałem CustomViewPager
ze sterowaniem suwakiem:
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);
}
}
Jeśli ustawisz canScroll
na true
, to ViewPager
można przesuwać palcem, false
wręcz przeciwnie.
Używam tego w moim projekcie i działa świetnie do tej pory.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-20 14:47:47
Spróbuj przesłonić i zwrócić true z onintercepttouchevent()i/lub onTouchEvent(), które pochłonie zdarzenia dotykowe na pagerze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-10 23:10:04
Inne łatwe rozwiązanie, aby wyłączyć przesuwanie na określonej stronie (w tym przykładzie Strona 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-01 04:48:46
Jeśli chcesz zaimplementować to samo dla Androida w Xamarin, tutaj jest tłumaczenie do C #
Wybrałem nazwę atrybutu"ScrollEnabled". Bo iOS używa tylko tego samego nazewnictwa. Tak więc masz równe nazewnictwo na obu platformach, co ułatwia programistom.
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;
}
}
}
W .plik 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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-03 07:14:18
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;
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-01 18:00:35
Proste rozwiązanie jest opisane tutaj: implementacja Zoomable ImageView poprzez rozszerzenie domyślnego Viewpagera w Phimpme Android (oraz GitHub sample-PhotoView):
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;
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 11:30:29
Żaden z powyższych kodów nie działa płynnie.próbowałem tego
<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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-06 14:07:22
Korzystałem z tej klasy z powodzeniem. Nadpisanie executeKeyEvent jest wymagane, aby uniknąć przesuwania za pomocą strzałek w niektórych urządzeniach lub dla dostępności:
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;
}
}
I w XML nazwij to tak:
<package.path.ViewPagerNoSwipe
android:layout_width="match_parent"
android:layout_height="match_parent" />
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-10 22:27:42