在ViewPager中滑动方向

时间:2014-07-13 10:06:39

标签: android android-viewpager swipe direction fragmentstatepageradapter

我有一个使用ViewPager和FragmentStatePagerAdapter的Android应用。然而,我需要添加一个新功能,我必须知道滑动方向从一个片段视图移动到另一个,左或右。 (即,当我向左滑动时,我会做一件事,当我向右滑动时,我会做其他事情。)

请注意,我不需要在滑动结束后发生事件。滑动发生时我必须做这些事件。我想过使用setOnPageChangeListener(),但它并没有告诉我滑动方向。你能告诉我如何找出滑动方向吗?

感谢。

9 个答案:

答案 0 :(得分:6)

查看ViewPager.OnPageChangeListeneronPageSelected(int position)方法。 position给出了新选择页面的索引。如果您跟踪当前页面索引,则可以将其与position索引进行比较,以获得滑动的左/右方向。

既然您提到OnPageChangeListener没有帮助,请考虑onInterceptTouchEvent (MotionEvent ev)的{​​{1}}方法。考虑到MotionEvent的ACTION_DOWN,ACTION_MOVE和ACTION_UP。希望这会有所帮助。

答案 1 :(得分:5)

我遇到了这个问题,需要知道正在发生的滑动的方向,以防止在某个方向滑动。这是我如何解决我的问题,希望它对某人有帮助。我发现前面的所有例子都不符合我的要求。

如果您继承了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;
    }
}

答案 2 :(得分:3)

这很简单,引入了一个实例变量来跟踪当前页面。

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

答案 3 :(得分:2)

也许你可以建立一个这样的监听器:

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 :(得分:2)

通过使用Kotlin和ViewPager2,这是我的解决方案,您可以将OnPageChangeCallback侦听器注册为下面的代码片段(仅向右滑动)

<Formik
  initialValues={{
    patients: [
      {
        id: "1",
        firstName: "",
        lastName: "",
        items: "",
      },
    ],
    phoneNumber: "",
    peopleOrdering: 1,
    monthOrder: "1",
    collectionOrDelivery: "",
    waitingOrLater: "",
    address: "",
    staffMember: "",
    claimReceipt: "",
    whereIsPrescription: "",
    keepSubscription: "",
    }}
    validationSchema={OrderSchema}
    onSubmit={() => {}}
>
  {({ values }) => (
    <Form>
      <FormItem name="patients">
        {values.patients.map((patient, i) => (
          <div key={patient}>
            <Input name={`patients[${i}].firstName`}></Input>
            <Input name={`patients[${i}].lastName`}></Input>
            <Input name={`patients[${i}].items`}></Input>
          </div>
        ))}
      </FormItem>
     // ... REST OF THE FORM
    </Form>
  )}
</Formik

答案 5 :(得分:1)

您实际上可以使用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){

                }
            }
        );

答案 6 :(得分:1)

您可以将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 :(得分:0)

我使用这个小实现来检测用户在滚动期间是向右滚动还是向左滚动。在某些我不知道的情况下,我可能会遇到一些错误但是我可以根据需要提出一些错误,而不必添加触摸监听器:

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 - >开始。我们可以在滚动的最开始检查一次该值,并仅在滚动结束时重置该标志。

我们将currentScrollDirection设置为空闲位置而不是onPageSelected,因为如果用户在滚动中间释放然后您将获得错误读取,则可以调用onPageSelected

答案 8 :(得分:-2)

您可以使用setOnPageChangeListener()并正确实施onPageScrolled(int position, float positionOffset, int positionOffsetPixels)

您可以通过positionOffset和位置变量检测方向:

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
   if(position == mCurrentPosition && positionOffset > 0)
   {
    //swipe right
   }
   else if (positionOffset > 0)
   {
   //swipe left
   }
}