Можно ли отключить прокрутку на ViewPager


144

У меня есть ViewPagerэкземпляр, который создает экземпляр View. Я хотел бы на мгновение отключить как прокрутку окна просмотра, так и дочерние кнопки, пока результат поиска возвращается в представление. Я звоню, viewPager.setEnabled(false)но это не отключает.

У кого-нибудь есть идеи?


Ответы:


366

Простое решение - создать собственный подкласс ViewPager, имеющий private booleanфлаг isPagingEnabled. Затем переопределить onTouchEventи onInterceptTouchEventметоды. Если isPagingEnabledравно true, вызвать superметод, в противном случае return.

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

Затем в своем Layout.XMLфайле замените <com.android.support.V4.ViewPager>теги <com.yourpackage.CustomViewPager>тегами.

Этот код был адаптирован из этого сообщения в блоге .


2
отличное решение, отлично работает. Если вы хотите прекратить смахивать, как обезьяна, вы можете переопределить OnPageChangeListener с помощью @Override public void onPageScrollStateChanged (final int state) {switch (state) {case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled (false); перемена; case ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled (true); перемена; } // noop}
— Informatic0re

13
PS: В XML используйте <yourpkgname.CustomViewPager ... вместо <com.android, support.v4.ViewPager ...
— thecr0w

чтобы добавить еще одно аналогичное решение, вы можете использовать библиотеку под названием «JazzyViewPager»: github.com/jfeinstein10/JazzyViewPager и просто вызвать setPagingEnabled (boolean)
— разработчик Android

можно ли остановить только прокрутку? я могу прокручивать только влево
— Саиф Хамед

По-прежнему можно «прокручивать», фокусируя элементы (кнопки и т. Д.) На страницах, например, при использовании игрового контроллера или клавиатуры. Как это полностью отключить? Я предполагаю, что это другой тип событий, которые следует перехватить ...
— Дэвид Ферран,

36

Для этого есть простое решение:

Если вы хотите отключить прокрутку окна просмотра, выполните следующие действия:

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

И когда вы захотите снова включить его, тогда:

mViewPager.setOnTouchListener(null);

Это поможет.


47
Почти, но не совсем. Приземление все еще происходит, поэтому вы можете перемещать страницы, выполняя множество небольших движений.
— Flynny75 06

@Akhil Sekharan столкнулся с проблемой, с которой столкнулся Флинни при использовании этого ответа ... но, к счастью, не знаю, как внезапно эта ошибка исчезла ... :) и работала как шарм !!
— Zombie

Вы можете делать много маленьких движений, поэтому вам все равно придется использовать публичное логическое значение onInterceptTouchEvent (событие MotionEvent) {ездить согласно ответу slatons
— Райан Хайтнер

28

Вот мой облегченный вариант ответа Слейтона:

public class DeactivatableViewPager extends ViewPager {
    public DeactivatableViewPager(Context context) {
        super(context);
    }

    public DeactivatableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !isEnabled() || super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return isEnabled() && super.onInterceptTouchEvent(event);
    }
}

С помощью моего кода вы можете отключить подкачку setEnable().


Переопределение onInterceptTouchEvent()не позволит дочерним представлениям получать ввод. В большинстве случаев это не предполагаемое поведение.
— Alex

20

Я нашел простое решение.

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

Это весь код, который вы использовали? У меня это не работает.
— Джаред Берроуз,

17
У меня не работает. Тем не менее можно делать много маленьких движений.
— DYS

Это неправильный код bcz Он очень медленно прокручивается, как висящий вид
— Ганшьям Найма

Это может сработать, если повезет. Обновление ViewPager может сломать этот взлом.
— Pointer Null

Он все еще тянется, но постепенно (.
— ekashking

14

Предлагаю другой способ решения этой проблемы. Идея заключается в том, чтобы обернуть ваш viewPager с помощью scrollView, так что, когда этот scrollView не прокручивается, ваш viewPager тоже не прокручивается.

Вот мой XML-макет:

        <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/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

Код не нужен.

У меня отлично работает.


1
Среди всех этих ответов я считаю, что это просто и отлично работает !!
— SREE

ОК ... НО когда у вас есть карта как один из фрагментов во ViewPager, тогда ... это проблема
— ekashking

5

В моем случае использования ViewPager 2 alpha 2 работает приведенный ниже фрагмент.

viewPager.isUserInputEnabled = false

Возможность отключить ввод данных пользователем (setUserInputEnabled, isUserInputEnabled)

обратитесь к этому для получения дополнительных изменений в viewpager2 1.0.0-alpha02

Также были внесены некоторые изменения в последнюю версию ViewPager 2 alpha 4

Атрибуты ориентации и isUserScrollable больше не являются частью SavedState

обратитесь к этому для получения дополнительных изменений в viewpager2 # 1.0.0-alpha04


Если вы используете pager2, это правильный способ сделать это
— Адизбек Эргашев

4

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

 mViewPager.beginFakeDrag();

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

 mViewPager.endFakeDrag();

2
Прокрутка по-прежнему возможна, просто она больше не работает. По сути, это просто ухудшение качества без решения проблемы.
— Benjamin Basmaci

1
дублированный ответ
— Рикардо А.

3

Лучшее решение, которое сработало для меня:

public class DeactivatedViewPager extends ViewPager {

    public DeactivatedViewPager (Context context) {
        super(context);
    }

    public DeactivatedViewPager (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

После этого прокрутка будет отключена прикосновением, и вы все равно сможете использовать setCurrentItemметод для изменения страницы.


Не знаю почему, но это просто не сработало. Прокрутка по-прежнему происходит.
— Рикардо А.

1
В canScrollHorizontally()текущем сценарии метод не действует. Он даже не вызывается, когда происходит свайп.
— Alex

3

Вот ответ на Котлине и androidX

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}

2

Как насчет этого:
я использовал CustomViewPager
и затем переопределил метод scrollTo.
Я проверял движение при большом количестве небольших свайпов, он не прокручивается на другие страницы.

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

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}

У меня была проблема, что панель просмотра все еще делала небольшие смахивания, но переопределение View.scrollTo(int x, int y)решило эту проблему для меня. Спасибо
— Palm

В некоторых случаях это вызывает странное поведение. Как пойти в пустоту и оставить только пустую страницу '-'
— Рикардо А.

1

Новый класс ViewPager2 от androidx позволяет отключить прокрутку методом setUserInputEnabled (false)

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}

0

Ответ слэйтона работает нормально. Если вы хотите прекратить пролистывать, как обезьяна, вы можете переопределить OnPageChangeListener с помощью

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

Таким образом, вы можете проводить только бок о бок


1
Я не нашел никакого метода ViewPager, такого как setPagingEnabled (логическое значение)
— Ракеш Ядав

setPagingEnabled (логическое значение) должно быть создано вами, потому что нет такого метода для переопределения.
— Kharak

Непонятно, что setPagingEnabled()делает этот метод. Пожалуйста, укажите полный код.
— Alex

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

public NonSwipeableViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

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

Затем в файле Layout.XML замените все теги --- com.android.support.V4.ViewPager --- тегами --- com.yourpackage.NonSwipeableViewPager ---.


0

Я создал версию Kotlin на основе преобразования этого ответа с Java: https://stackoverflow.com/a/13437997/8023278

Не существует встроенного способа отключения перелистывания между страницами ViewPager, требуется расширение ViewPager, которое переопределяет onTouchEvent и onInterceptTouchEvent, чтобы предотвратить действие пролистывания. Чтобы сделать его более универсальным, мы можем добавить метод setSwipePagingEnabled для включения / отключения перелистывания между страницами.

class SwipeLockableViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    private var swipeEnabled = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onTouchEvent(event)
            false -> false
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onInterceptTouchEvent(event)
            false -> false
        }
    }

    fun setSwipePagingEnabled(swipeEnabled: Boolean) {
        this.swipeEnabled = swipeEnabled
    }
}

Затем в нашем макете xml мы используем наш новый SwipeLockableViewPager вместо стандартного ViewPager

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

Теперь в нашей активности / фрагменте мы можем вызывать, myViewPager.setSwipePagingEnabled(false)и пользователи не смогут перелистывать страницы


ОБНОВИТЬ

По состоянию на 2020 год у нас есть ViewPager2 . Если вы переходите на ViewPager2, есть встроенный метод отключения прокрутки:myViewPager2.isUserInputEnabled = false

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.