Как отключить пейджинг, проводя пальцем в ViewPager, но все же иметь возможность проводить программно?

550

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

theateist
источник
Как насчет использования 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" />

Этот конкретный пример в LinearLayoutи предназначен для всего экрана, поэтому layout_weight1 и layout_height0dp.

И setMyScroller();метод для плавного перехода

louielouie
источник
3
@louielouie С другой стороны: есть ли какая-то особая причина, почему вы выбрали решение 0dpроста / 1веса над match_parentростом, чтобы получить полноэкранный эффект? Вы получаете улучшения производительности, делая это?
Ubuntudroid
29
Этот ответ не предотвращает перелистывание страниц при использовании левой / правой клавиш клавиатуры (попробуйте в эмуляторе). Может не быть проблемой для сенсорных устройств, но с телевизором и ноутбуком это может быть одно.
Винсент Мимун-Прат
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 мог просто предоставить метод, к которому мы предоставляем наш метод интерфейса, как обрабатывать касания / смахивания, потому что я считаю, что это не повредит?
Neon Warge
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и пользователи не смогут пролистывать страницы.

Rajul
источник
3
Прекрасно работает для представления, имеющего несколько подпредставлений, в котором используется горизонтальная прокрутка (например, диаграмма AChartEngine). В своем фрагменте я использую обратный вызов своей деятельности, говоря ему, чтобы он включал или выключал подкачку в зависимости от того, коснулся ли пользователь (ACTION_MOVE) графика или покинул его (ACTION_CANCEL). Большое спасибо!
riper
32
Вы можете упростить свои методы onTouchEventи onInterceptTouchEventметоды с помощьюreturn enabled && super.onTouchEvent(event);
nbarraille
2
@nbarraille, это просто вопрос стиля. Вы можете использовать любой стиль, который кажется вам более читабельным.
Раджул
7
Я также рекомендовал бы изменить имя поля с «включено» на «swipePageChangeEnabled» или что-то подобное. Через месяц после написания кода вы вряд ли вспомните, что означает «включено», особенно когда ваш класс называется «CustomViewPager», где неясно, что такое настройка. Это также вопрос стиля, но стиль имеет значение, если вы не хотите закончить с неподдерживаемым проектом, его легче полностью переписать, чем исправить.
bytefu
4
Где я могу вызвать setPagingEnabled? ._.
Ntikki
107

Самый простой способ это setOnTouchListenerи вернуться trueна ViewPager.

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });
Wayne
источник
53
Не работает иногда. Я использую ViewPager с FragmentPagerAdapter и несколько Fragment. После установки OnTouchListener на пейджер, если я уйду влево, пользовательский интерфейс все еще будет немного двигаться влево.
Chris.Zou
16
Работает при добавлении pager.setCurrentItem(pager.getCurrentItem());перед возвратом true.
13:00
1
это работало на меня раньше. Понятия не имею, почему это больше не работает.
Android-разработчик
Кажется, работает для меня. Чтобы решить некоторые проблемы с макетом, у меня есть public int getItemPosition(Object object) { return POSITION_NONE; }в моем адаптере, который вызывает воссоздание страниц и, возможно, решение других проблем.
r-hold
6
Это ЧАСТИЧНО рабочее решение. Горизонтальные движения обрабатываются каким-то странным образом. Я проверил это с помощью Drag'n Drop Gridview как части ViewPager. При перетаскивании с использованием этого решения, перетаскивание слева направо и справа налево не выполняется. Лично я считаю подход Раджула лучшим.
Тон Сноэй,
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.

Pietro
источник
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. В этом случае правильное решение не сработало для меня.
Рафаэль Руис Муньос
останавливает анимацию тоже при использовании во вкладках.
Ришабх Шривастава
Если я отключу это и предположу, что я хочу включить это тогда, где я могу получить событие для вызова setSwipeLocked (false)?
Рави Ядав
58

Теперь нам не нужно создавать кастомы 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" />

Используя код

Чтобы отключить смахивание в viewpager2использовании

viewPager2.setUserInputEnabled(false);

Чтобы включить смахивание в viewpager2Использовать

viewPager2.setUserInputEnabled(true);

для получения дополнительной информации проверьте это

ОБНОВИТЬ

Нилеш Ратод
источник
3
Это здорово, но все еще выглядит неполным. Я попробовал это с 5 различными фрагментами, и после переключения между страницами один из фрагментов был как бы потерян, то есть вид не был ни восстановлен, ни повторно раздут
Toochka
@Toochka Жаль слышать, что для меня все работает нормально, пример рабочего кода можно найти здесь stackoverflow.com/a/54643817/7666442, если возможно, поделитесь своим кодом
Nilesh Rathod
1
Я мог бы успешно отключить смахивание на ViewPager2, используя этот метод
voghDev
1
@voghDev рад это слышать
Nilesh Rathod
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
Это не очень хорошее решение, потому что оно допускает небольшие движения, по крайней мере, в моем приложении.
koras
У меня отлично работает. Каковы недостатки по сравнению с другими решениями?
userM1433372
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событие.
Хаос
Разве это также не блокирует прикосновения в окне просмотра?
Android-разработчик
Да, это будет. Это ожидаемое поведение, требуемое OP @androiddeveloper
Dinuka Jay
@RickGrimesTheCoder Не думаю, что вы поняли мой вопрос. Я имею в виду взгляды внутри фрагментов видового экрана. Будут ли они по-прежнему осязаемы?
Android-разработчик
Нет, они не будут, так как у самого viewpager есть слушатель щелчка. Это подходит только для случаев, когда у вас нет интерактивных элементов внутри фрагментов. Например, Welcome 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 и я хочу щелкнуть мышью? это решение останавливает нажатие на все под viewpager ..
aimiliano
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" />
madx
источник
Оно работает. Только свайп отключен, а нажатие на вкладку включено. AS предупреждает, что performClick()метод не переопределен.
CoolMind
5

В Kotlin моё решение, сочетающее приведенные выше ответы.

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 Обнаружили ли вы какие-либо проблемы после реализации этого? Для некоторых действий я включил считывание элементов в окне рециркуляции, и он работает нормально. Так что реализация работает нормально в моем случае.
Сагар Чапагайн
Сагар Чапагейн: или, конечно, я сделал. Каждая из моих страниц содержит пользовательский вид, который обрабатывает прикосновения различными способами (включая прокрутку, перетаскивание, одиночные и длинные касания). Не вызывать super.onInterceptTouchEvent(event)результаты в этих представлениях, не получая никакого ввода (что является задокументированной целью onInterceptTouchEventметода).
Алекс Семенюк
Если это так, вы должны использовать дочерний фрагмент и поддерживать backstack.
Сагар Чапагайн
Какое отношение это имеет к текущему вопросу? Фрагменты помещаются в некоторые контейнеры (которые являются представлениями ), а их собственный макет содержит представления . Независимо от того, какой контент у меня есть внутри ViewPager, я все еще сталкиваюсь с тем фактом, что переопределяющий onInterceptTouchEvent()метод не позволяет ему (контенту) получать входные данные.
Алекс Семенюк
4

Попробуйте переопределить и вернуть true из onInterceptTouchEvent () и / или onTouchEvent () , которые будут использовать сенсорные события на пейджере.

AdamK
источник
1
не хочет ли он вернуться, trueчтобы подразумевать, что событие касания было обработано?
edthethird 3
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

Если вы напишите галерею изображений с символамиImageView s и 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;
        }
    }
}
CoolMind
источник
1

Если вы используете ViewPager2, вам просто нужно использовать:

viewpager.setUserInputEnabled(false);

Из документов :

Включить или отключить пользовательскую прокрутку. Это включает в себя сенсорный ввод (жесты прокрутки и перемещения) и ввод специальных возможностей. Отключение ввода с клавиатуры пока не поддерживается. Когда пользовательская прокрутка отключена, программная прокрутка через setCurrentItem все еще работает. По умолчанию пользовательская прокрутка включена.

Спасибо: https://stackoverflow.com/a/61685871/9026710

Тайяб Мажар
источник
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>
Lepidopteron
источник
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);

            }
             ...
           }
tamtom
источник
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);
}
}
Шивам Ядав
источник
-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
            }

        })
Cихат Байдан
источник