Як відключити пейджинг, провевши пальцем у ViewPager, але все-таки мати можливість програмувати пальцем?


549

У мене є ViewPager, а під ним у мене 10 кнопок. Натиснувши кнопку, наприклад, №4, пейджер негайно переходить на сторінку №4 mPager.setCurrentItem(3);. Але я хочу відключити підкачку, провевши пальцем по горизонталі. Таким чином, підкачка виконується ТОЛЬКО натисканням на кнопки. Отже, як я можу відключити промацування пальцем?


Як щодо використання ViewFlipper в першу чергу? Це позбавить вас від головного болю.
Олексій Семенюк

Відповіді:


885

Вам потрібно підклас ViewPager. onTouchEventУ ньому є багато хороших речей, які ви не хочете змінювати, як, наприклад, дозволяючи дітям переглядати погляди. onInterceptTouchEventце те, що ви хочете змінити. Якщо ви подивитесь на код для ViewPager, ви побачите коментар:

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

Ось повне рішення:

Спочатку додайте цей клас у свою 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*/);
        }
    }
}

Далі обов’язково використовуйте цей клас замість регулярного ViewPager, який ви, ймовірно, вказали як android.support.v4.view.ViewPager. У вашому файлі компонування ви хочете вказати його приблизно так:

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

Цей конкретний приклад міститься в a LinearLayoutі покликаний займати весь екран, тому layout_weight1 і layout_height0dp.

І setMyScroller();метод призначений для плавного переходу


3
@louielouie Побічна примітка: чи є якась конкретна причина, чому ви вибрали рішення з 0dpвисотою / 1вагою над match_parentвисотою для досягнення ефекту на весь екран? Чи отримуєте ви покращення ефективності, роблячи це?
ubuntudroid

28
Ця відповідь не перешкоджає розгортанню сторінки при використанні клавіатури вліво / вправо (спробуйте її в емуляторі). Це може не бути проблемою для сенсорних пристроїв, але для телевізора та ноутбуків це може бути одне.
Вінсент Мімон-Прат

8
@MarvinLabs @Thorbear Правильний спосіб відключення прокрутки сторінки за допомогою клавіатури - це переосмислення executeKeyEvent(). Це метод, який потім викликають allowScroll(). // Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
аракс

6
ну, це також відключає вертикальну прокрутку ... це погано, якщо ви використовуєте перегляд списків.
Майсі

5
Я сподіваюся, що Google може просто запропонувати метод, яким ми надаємо наш метод інтерфейсу щодо того, як обробляти дотики / пальці, оскільки я вважаю, що це не зашкодить?
Неонова війна

466

Більш загальним розширенням ViewPagerбуло б створити SetPagingEnabledметод, щоб ми могли вмикати та вимикати підкачки під час польоту. Щоб увімкнути / відключити прокручування, просто перекрийте два способи: onTouchEventі onInterceptTouchEvent. Обидва повернуть "помилково", якщо підказка була відключена.

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

Потім виберіть це замість вбудованого проглядача в XML

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

Вам просто потрібно зателефонувати за допомогою setPagingEnabledметоду, falseі користувачі не зможуть провести пальцем до сторінки.


3
Ідеально підходить для подання, яке має кілька підзаглядів, де використовується горизонтальна прокрутка (наприклад, діаграма AChartEngine). У своєму фрагменті я використовую зворотний дзвінок до своєї діяльності, вказуючи на його вимкнення або вимкнення підкачки, залежно від того, чи торкнувся користувач (ACTION_MOVE) діаграми чи залишив її (ACTION_CANCEL). Дуже дякую!
riper

32
Ви можете спростити свої onTouchEventта onInterceptTouchEventметоди за допомогоюreturn enabled && super.onTouchEvent(event);
nbarraille

2
@nbarraille - це лише питання стилю. Ви можете використовувати будь-який стиль, який здається вам більш зрозумілим.
Раджул

7
Я також рекомендую змінити назву поля з "включеного" на "swipePageChangeEnabled" або щось подібне. Через місяць після написання коду ви навряд чи пам’ятаєте, що означає «включений», особливо коли ваш клас називається «CustomViewPager», де не зрозуміло, що таке налаштування. Це теж питання стилю, але стиль має значення, якщо ви не хочете закінчувати непідтримуваний проект, то простіше переписати повністю, ніж виправити.
bytefu

3
Де я називаю setPagingEnabled? ._.
Ntikki

107

Найпростіший спосіб - setOnTouchListenerповернутися trueдо ViewPager.

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

53
Іноді не працює. Я використовую ViewPager з FragmentPagerAdapter та декількома фрагментами. Після встановлення OnTouchListener на пейджер, якщо я перекину ліворуч, користувальницький інтерфейс все одно трохи перейде вліво.
Chris.Zou

16
Він працює при додаванні pager.setCurrentItem(pager.getCurrentItem());перед поверненням true.
DNG

1
це працювало на мене раніше. поняття не знаю, чому це вже не працює добре.
андроїд розробник

здається, працює на мене. Для вирішення деяких глюків у компоновці у мене є public int getItemPosition(Object object) { return POSITION_NONE; }адаптер, який змушує відтворити сторінки і, можливо, вирішити і інші проблеми.
r-утримуйте

6
Це ЧАСОВЕ робоче рішення. Горизонтальні повороти обробляються якось дивно. Я перевірив це за допомогою Drag'n Drop Gridview як частини ViewPager. Перетягуючи за допомогою цього рішення, перетягування зліва направо і справа наліво не вдається. Особисто я вважаю підхід Раджула найкращим.
Ton Snoei

58

Краще оголосити його стильним, щоб ви могли змінити його властивість з 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;
}

І у своїх значеннях / attr.xml:

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

щоб ви могли використовувати його у вашому макеті 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" />

Звичайно, ви все ще можете мати властивість get / set.


58

Перевизначення лише onTouchEventі onInterceptTouchEventнедостатньо у випадку, якщо ви переглянете сам ViewPager в інший ViewPager. Дочірній ViewPager вкраде горизонтальні події сенсорного прокрутки у батьківського ViewPager, якщо вони не розміщені на першій / останній сторінці.

Щоб правильно налаштувати цю установку, вам також потрібно перекрити canScrollHorizontallyметод.

Дивіться LockableViewPagerвиконання нижче.

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
Дякую, це дуже добре працює на ViewPager всередині іншого ViewPager.
Фернанда Барі

1
Це працює для мене, також для ViewPager всередині іншого ViewPager. Правильне рішення не спрацювало для мене в такому випадку.
Рафаель Руїс Муньос

також зупиняє анімацію при використанні на вкладках.
Rishabh Srivastava

Якщо я відключу його і припускаю, що я хочу його включити, то де я можу отримати подію для виклику setSwipeLocked (false)?
Раві Ядав

57

Зараз нам не потрібно створювати на замовлення ViewPager

Нове ViewPager2 ім'я Перегляд доступне в android

Підтримка вертикальної орієнтації

  • ViewPager2підтримує вертикальне пейджінг на додаток до традиційного горизонтального підкачки. Ви можете ввімкнути вертикальний пейджинг для ViewPager2елемента, встановивши його android:orientationатрибут

Використання XML

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

Використання коду

Щоб відключити Swiping в viewpager2використанні

viewPager2.setUserInputEnabled(false);

Щоб увімкнути розмикання в режимі viewpager2Використання

viewPager2.setUserInputEnabled(true);

для отримання додаткової інформації перевірте це

ОНОВЛЕННЯ


3
Це чудово, але все ж виглядає неповним. Я спробував це з 5 різними фрагментами, і після перемикання між сторінками один із фрагментів був
Toochka

@Toochka вибачте за те, що для мене це працює чудово, ви можете знайти зразок робочого коду звідси stackoverflow.com/a/54643817/7666442, якщо можливо, будь ласка, поділіться своїм кодом
Nilesh Rathod

1
Я міг успішно відключити перехід на ViewPager2 за допомогою цього методу
voghDev

1
@voghDev із задоволенням почув це
Нілеш

1
@PhaniRithvij ласка , перевірте цю відповідь stackoverflow.com/a/54643817/7666442 я Додали всі деталі , як використовувати viewpager2зRecyclerView.Adapter
Nilesh Rathod

35

Якщо ви продовжуєте роботу з ViewPager, ви також повинні перекрити,executeKeyEvent як зазначено раніше від @araks

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

Оскільки на деяких пристроях, таких як Galaxy Tab 4 10 ', відображаються ці кнопки там, де більшість пристроїв ніколи їх не показує:

Кнопки клавіатури


50
Samsung завжди накручує речі для Android розробників.
toobsco42

2
@ toobsco42 У цьому випадку Samsung не самотній. SwiftKey (популярний додаток для клавіатури) дозволяє користувачам класти стрілки на свої клавіатури.
Суфіан

1
Це також виправлення, якщо ви хочете зупинити когось, який використовує клавіатуру / трекербол, щоб підзивати пейджер.
se22as

28

Щоб вимкнути функцію пальця

mViewPager.beginFakeDrag();

Щоб увімкнути перехід пальцем

mViewPager.endFakeDrag();

22
Це не гарне рішення, тому що воно дозволяє невеликі порції руху, принаймні в моєму додатку.
корас

Добре працює для мене. Які недоліки порівняно з іншими наданими рішеннями?
користувачM1433372

13

Мені потрібно було відключити перехід на одній конкретній сторінці та надати їй приємну анімацію на гумці, ось як:

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

Він чекає, поки наступна сторінка буде частково видно. Код для наступної сторінки в onPageSelectedбуде виконано. Навіть наступна сторінка переключиться. Отже, цей код не потрібен.
CoolMind

13

Я знаю, що це дуже пізно, щоб опублікувати це, але ось крихітний хак для досягнення вашого результату;)

Просто додайте фіктивний вигляд під панель перегляду:

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

Потім додайте OnClickListenerсвій RelativeLayout.

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

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

Будьте трохи креативні з макетами, їх розміщеннями та поведінкою, і ви навчитеся знаходити спосіб робити абсолютно все, що ви собі уявляєте :)

Удачі!


Простішим способом є використання setClickableзамість цього setOnClickListener, якщо вам не потрібно обробляти onClickподії.
Хаос

Чи не буде це також блокувати дотики в панелі перегляду?
андроїд розробник

Так, буде. Це очікувана поведінка, яку вимагає OP @androiddeveloper
Dinuka Jay

@RickGrimesTheCoder Я не думаю, що ти зрозумів моє запитання. Я маю на увазі погляди в фрагментах оглядача. Чи будуть вони ще дотикові?
андроїд розробник

Ні, їх не буде, оскільки у самого оглядача є прослуховувач клацань. Це підходить лише для випадків, коли у вас немає інтерактивних елементів у фрагментах. Наприклад, привітання ViewPager, який динамічно змінює свої фрагменти @androiddeveloper
Dinuka Jay,

12

Я написав CustomViewPagerконтрольний простір:

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

Якщо ви встановите canScrollна trueце ViewPagerможе бути б'ючи палець, falseнавпаки.

Я використовую це у своєму проекті, і він чудово працює дотепер.


1
Що робити, якщо у мене є кнопка всередині ViewPager, і я хочу натиснути? це рішення зупиняє все натискання
панелі перегляду

6

Я використовував цей клас із успіхом. Перевизначення executeKeyEvent потрібно , щоб уникнути зчитування з допомогою стрілок в деяких пристроях або для доступності:

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

}

І в xml називаємо це так:

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

Це працює. Тільки проведіть пальцем, і натискання на вкладку ввімкнено. AS попереджає, що performClick()метод не буде перекрито.
CoolMind

5

У Котліні моє рішення, поєднуючи відповіді вище.

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

Переоцінка onInterceptTouchEvent()перешкоджатиме переглядам дочірніх даних отримувати інформацію. У більшості випадків це не призначена поведінка.
Олексій Семенюк

Мені вдалося взаємодіяти з дитячими поглядами на кожен фрагмент. Не впевнений, на що йдеться.
Джефф

5

У kotlin ми можемо вирішити це, створивши користувацький віджет, що успадковує клас ViewPager, та додавши значення прапорця для контролю поведінки пальців.

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

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

Вимкнути програмування. Якщо kotlin-android-extensionsплагін застосований у build.gradle , розгортання можна відключити, записавши нижче код.

view_pager.pagingEnabled = false

В іншому випадку ми можемо відключити перенесення за допомогою наведеного нижче коду:

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

Переоцінка onInterceptTouchEvent()перешкоджатиме переглядам дочірніх даних отримувати інформацію. У більшості випадків це не призначена поведінка.
Олексій Семенюк

@AlexSemeniuk Чи спостерігали ви якусь проблему після впровадження цього? Я ввімкнув перехід на елементи перегляду утилізатора для деяких дій, і це працює нормально. Тож реалізація в моєму випадку прекрасно працює.
Sagar Chapagain

Sagar Chapagain: або, звичайно, я. Кожна з моїх сторінок містить спеціальний вигляд, який обробляє дотики різними способами (включаючи прокручування, перетягування, одинарне та довге торкання). Якщо виклик super.onInterceptTouchEvent(event)результатів у цих представленнях не отримує жодного вводу (що є задокументованою метою onInterceptTouchEventметоду).
Олексій Семенюк

У такому випадку вам слід скористатися дочірнім фрагментом і підтримувати backstack.
Sagar Chapagain

Наскільки це стосується поточного питання? Фрагменти поміщаються всередині деяких контейнерів (які перегляди ) і їх власний макет містить перегляди . Незалежно від того, який вміст у мене знаходиться у ViewPager, я все ще маю справу з тим, що переосмислювальний onInterceptTouchEvent()метод заважає йому (контенту) отримувати введення.
Олексій Семенюк


1

Ще одне просте рішення для відключення переходу на певну сторінку (у цьому прикладі, сторінка 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

Якщо ви пишете галерею зображень за допомогою ImageViews і ViewPager, що підтримує масштабування та панорамування, див. Тут описане просте рішення: Реалізація масштабованого ImageView шляхом розширення ViewPager за замовчуванням у програмі Phimpme Androidзразок Github - PhotoView ). Це рішення не працює з 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;
        }
    }
}

0

Якщо ви хочете реалізувати те саме для Android у Xamarin, ось переклад на C #

Я вирішив назвати атрибут " ScrollEnabled ". Тому що iOS просто використовує екзат-те саме іменування. Отже, ви маєте однакові імена на обох платформах, це полегшує розробникам.

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

У файлі .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

Жоден з наведених вище кодів не працює безперебійно. Я спробував це

<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

ось моя реалізація
що якщо ви хочете відключити анімацію при проведенні пальців, ви можете використовувати swipeListener вліво і вправо, і все ще хочете прокрутити пальцем, але без анімації

1- Viewpagerметод переосмислення onInterceptTouchEventтаonTouchEvent

2- створити свій власний GestureDetector

3- виявити жест пальцем і скористатися 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();
    }
}

коли налаштовано ViewPager, встановіть 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

Я лише трохи налаштував переглядач і відключити прокрутку легко.

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

Якщо ви використовуєте ViewPager2, ви просто повинні використовувати:

viewpager.setUserInputEnabled(false);

З документів :

Увімкнути або вимкнути прокручування, ініційовану користувачем. Сюди входить сенсорне введення (жести прокрутки та кидання) та введення доступності. Вимкнення введення з клавіатури ще не підтримується. Коли ініційована користувачем прокрутка вимкнена, програмні прокрутки через setCurrentItem все ще працюють. За замовчуванням увімкнено прокручування, ініційовану користувачем.

Дякуємо: https://stackoverflow.com/a/61685871/9026710


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

        })
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.