Можно ли отключить прокрутку на 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>тегами.

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

Slayton
источник
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().

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

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

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
Yessy
источник
Это весь код, который вы использовали? У меня это не работает.
Джаред Берроуз,
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; 
        } 
    }

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

Informatic0re
источник
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

Мэтт Смит
источник