Прокручивание направления в ViewPager
У меня есть приложение для Android, которое использует ViewPager и FragmentStatePagerAdapter. Однако мне нужно добавить новую функцию, в которой я должен знать направление движения, чтобы перейти от одного фрагмента к другому, влево или вправо. (то есть, когда я прокручиваю влево, я сделаю одно, а когда я проведу правой рукой, я сделаю что-то еще).
Обратите внимание: мне не нужны события, чтобы произойти ПОСЛЕ завершения салфетки. Я должен делать эти события, когда происходит салфетка. Я думал об использовании setOnPageChangeListener()
, но он не говорит мне о том, как двигаться. Можете ли вы посоветовать мне, пожалуйста, как определить направление движения?
Спасибо.
Ответы
Ответ 1
Взгляните на метод onPageSelected(int position)
ViewPager.OnPageChangeListener. position
указывает индекс только что выбранной страницы. Если вы отслеживаете текущий индекс страницы, вы можете сравнить его с индексом position
, чтобы получить направление влево/вправо.
Теперь, когда вы указываете, что OnPageChangeListener не помогает, рассмотрите метод onInterceptTouchEvent (MotionEvent ev)
ViewPager
. Учитывайте MotionEvent ACTION_DOWN, ACTION_MOVE и ACTION_UP. Надеюсь, это поможет.
Ответ 2
Я столкнулся с этой проблемой и должен знать направление движения, как это происходило, чтобы предотвратить прокрутку в определенном направлении. Вот как я решил свою проблему, надеюсь, это полезно кому-то. Я нашел все предыдущие примеры неэффективными для того, что мне было нужно.
Если вы подклассифицируете ViewPager, вы можете ответить на onInterceptTouchEvent(MotionEvent event)
и onTouchEvent(MotionEvent event)
методы ViewPager
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
// Do what you want here with left/right swipe
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean wasSwipeToRight = this.wasSwipeToRightEvent(event));
// Do what you want here with left/right swipe
return super.onTouchEvent(event);
}
Вот метод, который вызывается для определения направления события.
// Stores the starting X position of the ACTION_DOWN event
float downX;
/**
* Checks the X position value of the event and compares it to
* previous MotionEvents. Returns a true/false value based on if the
* event was an swipe to the right or a swipe to the left.
*
* @param event - Motion Event triggered by the ViewPager
* @return - True if the swipe was from left to right. False otherwise
*/
private boolean wasSwipeToRightEvent(MotionEvent event){
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
return false;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
return downX - event.getX() > 0;
default:
return false;
}
}
Ответ 3
Возможно, вы можете создать слушателя следующим образом:
buttonIcons.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
return true;
case MotionEvent.ACTION_UP:
upX = event.getX();
final float deltaX = downX - upX;
if (deltaX > 0 && deltaX > SWIPE_MIN_DISTANCE) {
final Animation loadInAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_in_right);
final Animation loadOutAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_out_left);
viewFlipper.setInAnimation(loadInAnimation);
viewFlipper.setOutAnimation(loadOutAnimation);
viewFlipper.showPrevious();
startSaveButtonAnimation();
}
if (deltaX < 0 && -deltaX > SWIPE_MIN_DISTANCE) {
final Animation loadInAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_in_left);
final Animation loadOutAnimation = AnimationUtils
.loadAnimation(
activity.this,
R.anim.slide_out_right);
viewFlipper.setInAnimation(loadInAnimation);
viewFlipper.setOutAnimation(loadOutAnimation);
viewFlipper.showNext();
startSaveButtonAnimation();
}
return true;
}
return false;
}
});
Ответ 4
Фактически вы можете найти направление с использованием параметров onPageScrolled
.
Следующий слушатель установлен для отображения лог-сообщения один раз на направление изменения чистого фрагмента (слева, если левые фрагменты отображаются, в центре, если фрагмент не отображается, справа, если показывает правый фрагмент).
Переменные класса, необходимо отслеживать
// -1 - left, 0 - center, 1 - right
private int scroll = 0;
// set only on `onPageSelected` use it in `onPageScrolled`
// if currentPage < page - we swipe from left to right
// if currentPage == page - we swipe from right to left or centered
private int currentPage = 0;
// if currentPage < page offset goes from `screen width` to `0`
// as you reveal right fragment.
// if currentPage == page , offset goes from `0` to `screen width`
// as you reveal right fragment
// You can use it to see
//if user continue to reveal next fragment or moves it back
private int currentOffset = 0;
// behaves similar to offset in range `[0..1)`
private float currentScale = 0;
Слушатель
pager.addOnPageChangeListener(
new OnPageChangeListener(){
@Override
public void onPageScrolled(int page, float scale, int offset){
if(scale != 0f && offset > 10){
if(currentOffset > offset && currentScale > scale && (page + 1) == currentPage){
if(scroll != -1){
newImageSet = true;
scroll = -1;
Log.e("scroll", "left");
}
} else if(currentOffset < offset && currentScale < scale && page == currentPage){
if(scroll != 1){
newImageSet = true;
scroll = 1;
Log.e("scroll", "right");
}
}
currentOffset = offset;
currentScale = scale;
}
@Override
public void onPageSelected(int i){
Log.e("scroll","centre");
// we are centerd, reset class variables
currentPage = i;
currentScale = 0;
currentOffset = 0;
scroll = 0;
}
@Override
public void onPageScrollStateChanged(int i){
}
}
);
Ответ 5
Это достаточно просто с введением переменной экземпляра, чтобы отслеживать текущую страницу.
public class MyActivity extends Activity implements ViewPager.OnPageChangeListener {
private ViewPager viewPager;
private int currentPosition;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Do trivial stuff
.
.
.
viewPager.setOnClickListener(this); // doesnt have to be in onCreate
}
@Override
public void onPageSelected(int position) {
if(currentPosition < position) {
// handle swipe LEFT
} else if(currentPosition > position){
// handle swipe RIGHT
}
currentPosition = position; // Update current position
}
}
Ответ 6
Вы можете добавить OnPageChangeListner в ViewPager и сделать что-то вроде этого:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
float tempPositionOffset = 0;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position == 0) {
if (tempPositionOffset < positionOffset) {
Log.d("eric", "scrolling left ...");
} else {
Log.d("eric", "scrolling right ...");
}
tempPositionOffset = positionOffset;
Log.d("eric", "position " + position + "; " + " positionOffset " + positionOffset + "; " + " positionOffsetPixels " + positionOffsetPixels + ";");
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Ответ 7
Я использую эту небольшую реализацию, чтобы определить, прокручивается ли пользователь вправо или влево во время самой прокрутки. У меня могут быть некоторые ошибки при определенных условиях, о которых я не знаю, но это то, что я мог бы придумать для того, что мне было нужно, не добавляя слушателя касания:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int SCROLLING_RIGHT = 0;
int SCROLLING_LEFT = 1;
int SCROLLING_UNDETERMINED = 2;
int currentScrollDirection = 2;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (isScrollDirectionUndetermined()){
setScrollingDirection(positionOffset);
}
if (isScrollingLeft()){
Log.i("TabLayout","Scrolling LEFT");
}
if (isScrollingRight()){
Log.i("TabLayout","Scrolling RIGHT");
}
}
private void setScrollingDirection(float positionOffset){
if ((1-positionOffset)>= 0.5){
this.currentScrollDirection = SCROLLING_RIGHT;
}
else if ((1-positionOffset)<= 0.5){
this.currentScrollDirection = SCROLLING_LEFT;
}
}
private boolean isScrollDirectionUndetermined(){
return currentScrollDirection == SCROLLING_UNDETERMINED;
}
private boolean isScrollingRight(){
return currentScrollDirection == SCROLLING_RIGHT;
}
private boolean isScrollingLeft(){
return currentScrollDirection == SCROLLING_LEFT;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE){
this.currentScrollDirection = SCROLLING_UNDETERMINED;
}
}
});
Мы можем определить направление прокрутки, потому что, когда пользователь прокручивается слева направо, positionOffset
переходит из 0 → 1, а при прокрутке справа налево он переходит от 1 → 0. Затем мы можем проверить это значение один раз в самом начале прокрутки и reset флаг только в конце прокрутки.
Мы устанавливаем currentScrollDirection
неопределенным в позиции idle вместо onPageSelected
, потому что onPageSelected
может вызываться, если пользователь освобождается в середине прокрутки, а затем вы получите ложное показание.
Ответ 8
Вы можете использовать setOnPageChangeListener()
и правильно реализовать onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
.
Вы можете определить направление по положениюOffset и положению:
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
if(position == mCurrentPosition && positionOffset > 0)
{
//swipe right
}
else if (positionOffset > 0)
{
//swipe left
}
}