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

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

Вам нужно подclassифицировать 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. */ 

Вот полное решение:

Сначала добавьте этот class в свою папку 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*/); } } } 

Затем убедитесь, что этот class используется вместо обычного ViewPager, который вы, вероятно, указали как файл android.support.v4.view.ViewPager. В вашем файле макета вам нужно указать его с чем-то вроде:

  

Этот конкретный пример находится в LinearLayout и предназначен для охвата всего экрана, поэтому layout_weight равен 1, а layout_height – 0dp.

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

Более общим расширением ViewPager было бы создание метода SetPagingEnabled чтобы мы могли включать и отключать пейджинг «на лету». Чтобы включить / отключить прокрутку, просто переопределите два метода: onTouchEvent и onInterceptTouchEvent . Оба будут возвращать «false», если пейджинг был отключен.

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

Затем выберите это вместо встроенного viewpager в XML

  

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

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

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

Лучше объявить его стильным, поэтому вы можете изменить его свойство из 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:

    

так что вы можете использовать его в своем макете xml:

  

Конечно, вы все равно можете получить свойство get / set.

Переопределение только onTouchEvent и onInterceptTouchEvent недостаточно, если у вас есть ViewPager непосредственно внутри другого ViewPager. Child 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); } } 

Отключение салфетки

 mViewPager.beginFakeDrag(); 

Чтобы включить салфетки

 mViewPager.endFakeDrag(); 

Если вы расширяетесь от ViewPager, вы также должны переопределить executeKeyEvent как указано ранее, @araks

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

Поскольку некоторые устройства, такие как Galaxy Tab 4 10 ‘, показывают эти кнопки, где большинство устройств никогда не показывают их:

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

Мне нужно было отключить прокрутку на одной конкретной странице и дать ей приятную анимацию в резиновых полосах, вот как это сделать:

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

Я знаю, что это может быть поздно опубликовать, но вот крошечный взломать для достижения вашего результата;)

Просто добавьте фиктивный вид под своим viewpager:

     

Затем добавьте OnClickListener в RelativeLayout .

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

Получите немного креатив с макетами, их местами размещения и их поведением, и вы научитесь находить способ сделать абсолютно все, что вы себе представляете 🙂

Удачи!

Я написал CustomViewPager с помощью 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 – наоборот.

Я использую это в своем проекте, и он отлично работает до сих пор.

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

Еще одно простое решение отключить прокрутку на определенной странице (в этом примере на стр. 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; } 

Если вы хотите реализовать то же самое для 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:

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

Здесь описано простое решение: реализация масштабируемого ImageView путем расширения стандартного ViewPager в Phimpme Android (и образец Github – PhotoView ):

 public class CustomViewPager extends ViewPager { public CustomViewPager(Context context) { super(context); } public CustomViewPager(Context context, AttributeSet attrs) { super(context,attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { try { return super.onInterceptTouchEvent(event); } catch (IllegalArgumentException e) { return false; } } } 

Ни один из приведенных выше кодов не работает плавно. Я попробовал это

    

Я использовал этот class с успехом. Переопределение execKeyEvent требуется, чтобы избежать прокрутки с использованием стрелок на некоторых устройствах или для доступности:

 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 назовите это так:

  
  • Как мы можем обойти пустой заголовок в PagerTitleStrip и PagerTabStrip?
  • Изменение продолжительности анимации ViewPager при программном программировании
  • android.content.res.Resources $ NotFoundException: Не удается найти идентификатор ресурса # 0xffffffff
  • Реализация круговой прокрутки в PagerAdapter
  • Как вы получаете текущий номер страницы ViewPager для Android?
  • Бесконечный ViewPager
  • Давайте будем гением компьютера.