Я использую ViewPager, состоящий из 6 страниц для отображения некоторых данных. Я хочу, чтобы иметь возможность вызвать метод, когда пользователь находится в позиции 0, и пытается пронести вправо (назад) или в позиции 5 и пытается пронестись влево (вперед), даже если для этих страниц не существует больше страниц направления. Есть ли способ прослушать эти сценарии?
ViewPager обнаруживает, когда пользователь пытается вывести из пределов
Ответ 1
Расширьте ViewPager и переопределите onInterceptTouchEvent()
следующим образом:
public class CustomViewPager extends ViewPager {
float mStartDragX;
OnSwipeOutListener mListener;
public void setOnSwipeOutListener(OnSwipeOutListener listener) {
mListener = listener;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float x = ev.getX();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartDragX = x;
break;
case MotionEvent.ACTION_MOVE:
if (mStartDragX < x && getCurrentItem() == 0) {
mListener.onSwipeOutAtStart();
} else if (mStartDragX > x && getCurrentItem() == getAdapter().getCount() - 1) {
mListener.onSwipeOutAtEnd();
}
break;
}
return super.onInterceptTouchEvent(ev);
}
public interface OnSwipeOutListener {
public void onSwipeOutAtStart();
public void onSwipeOutAtEnd();
}
}
Ответ 2
Ответ от Флавио Фариа не работает для меня. Единственным событием, которое я получаю onInterceptTouchEvent(), является событие ACTION_DOWN. Поэтому я переопределяю метод onTouchEvent(), чтобы заставить его работать.
Вот код. Обратите внимание, что у меня есть только onSwipeOutAtEnd() в слушателе. Вы можете добавить свой код, чтобы поддерживать прокрутку влево на первом vier.
public class CustomViewPager extends ViewPager {
float mStartDragX;
OnSwipeOutListener mListener;
public void setOnSwipeOutListener(OnSwipeOutListener listener) {
mListener = listener;
}
@Override
public boolean onTouchEvent(MotionEvent ev){
if(getCurrentItem()==getAdapter().getCount()-1){
final int action = ev.getAction();
float x = ev.getX();
switch(action & MotionEventCompat.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
mStartDragX = x;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (x<mStartDragX){
mListener.onSwipeOutAtEnd();
}else{
mStartDragX = 0;
}
break;
}
}else{
mStartDragX=0;
}
return super.onTouchEvent(ev);
}
public interface OnSwipeOutListener {
public void onSwipeOutAtEnd();
}
Ответ 3
Как насчет установки OnPageChangeListener на вашем ViewPager? Затем вы можете изменить свои стрелки навигации или что угодно в onPageScrolled.
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
updateNavigationArrows();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Ответ 4
Большое спасибо @Flavio, хотя мне пришлось внести некоторые изменения в его код, потому что методы обратного вызова дважды стреляли, также я добавил код, чтобы проверить, есть ли зарегистрированный прослушиватель, чтобы избежать сбоя приложения, когда нет прослушивателя зарегистрировано. Это код, который я использовал, чтобы заставить его работать: с onSwipeOutAtStart и onSwipeOutAtEnd:
public class CustomViewPager extends android.support.v4.view.ViewPager {
float mStartDragX;
OnSwipeOutListener mOnSwipeOutListener;
public CustomViewPager(Context context) {
super(context);
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnSwipeOutListener(OnSwipeOutListener listener) {
mOnSwipeOutListener = listener;
}
private void onSwipeOutAtStart() {
if (mOnSwipeOutListener!=null) {
mOnSwipeOutListener.onSwipeOutAtStart();
}
}
private void onSwipeOutAtEnd() {
if (mOnSwipeOutListener!=null) {
mOnSwipeOutListener.onSwipeOutAtEnd();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
mStartDragX = ev.getX();
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev){
if(getCurrentItem()==0 || getCurrentItem()==getAdapter().getCount()-1){
final int action = ev.getAction();
float x = ev.getX();
switch(action & MotionEventCompat.ACTION_MASK){
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (getCurrentItem()==0 && x>mStartDragX) {
onSwipeOutAtStart();
}
if (getCurrentItem()==getAdapter().getCount()-1 && x<mStartDragX){
onSwipeOutAtEnd();
}
break;
}
}else{
mStartDragX=0;
}
return super.onTouchEvent(ev);
}
public interface OnSwipeOutListener {
void onSwipeOutAtStart();
void onSwipeOutAtEnd();
}
}
Ответ 5
Интересно, как это сработало для других, это не работает для меня.
onInterceptTouchEvent()
принимает только событие ACTION_DOWN
. Пока onTouchEvent()
принимает только одно событие за раз: ACTION_DOWN
, ACTION_UP
и другие.
Мне пришлось переопределить как onInterceptTouchEvent()
, так и onTouchEvent()
, чтобы он работал правильно. ACTION_DOWN
of onInterceptTouchEvent
захватывает начальную точку X
, а OnTouchEvent
захватывает конечную точку X2
. Который я сравнил его, чтобы определить направление движения.
Получить начальное значение X касания:
float x1 = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch(ev.getAction() & MotionEventCompat.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
break;
}
return super.onInterceptTouchEvent(ev);
}
Из кода tjlian616 onTouchEvent()
прослушивает ACTION_UP
и получает его последним X
Значение.
Пока я установил, что текущее значение элемента равно 0, чтобы получить салфетки в стартовом прослушивании. По сравнению с ним и добавьте активированный слушатель.
@Override
public boolean onTouchEvent(MotionEvent ev){
if(getCurrentItem()==0){
final int action = ev.getAction();
switch(action & MotionEventCompat.ACTION_MASK){
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
mStartDragX = ev.getX();
if (x1<mStartDragX){
Log.i("TOUCH: ", "ACTION UP " + x1 + " : " + mStartDragX );
mListener.onSwipeOutAtStart();
}else{
Log.i("TOUCH ELSE : ", "ACTION UP " + x1 + " : " + mStartDragX );
mStartDragX = 0;
}
break;
}
}else{
mStartDragX=0;
}
return super.onTouchEvent(ev);
}