【问题标题】:Swipe Direction in ViewPager在 ViewPager 中滑动方向
【发布时间】:2014-09-03 11:37:37
【问题描述】:

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

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

谢谢。

【问题讨论】:

    标签: android android-viewpager swipe direction fragmentstatepageradapter


    【解决方案1】:

    我遇到了这个问题,需要知道滑动的方向因为它正在发生,以防止向某个方向滑动。这是我解决问题的方法,希望对某人有所帮助。我发现前面的所有示例都无法满足我的需要。

    如果您将 ViewPager 子类化,则可以响应 ViewPageronInterceptTouchEvent(MotionEvent event)onTouchEvent(MotionEvent event) 方法

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

    【讨论】:

    • downX 对我来说总是返回 0.0
    • @Roon13 是 event.getX() 在您触摸屏幕时返回一个值?
    【解决方案2】:

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

    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】:

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

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

      【讨论】:

        【解决方案4】:

        也许你可以像这样构建一个监听器:

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

        【讨论】:

        • 非常感谢!有效!。我已经为此苦苦挣扎了很长时间!。
        【解决方案5】:

        我使用这个小实现来检测用户在滚动过程中是向右还是向左滚动。在某些我不知道的情况下,我可能会遇到一些错误,但这是我无需添加触摸侦听器就可以解决我需要的问题:

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

        我们在空闲位置将currentScrollDirection 设置为未确定,而不是onPageSelected,因为如果用户在滚动过程中释放onPageSelected 可能会被调用,然后您会得到错误的读数。

        【讨论】:

          【解决方案6】:

          其实你可以通过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){
          
                          }
                      }
                  );
          

          【讨论】:

            【解决方案7】:

            您可以将 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) {
            
                    }
                });
            

            【讨论】:

              【解决方案8】:

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

              val pager = rootView.findViewById<ViewPager2>(R.id.viewPager).apply {
                      registerOnPageChangeCallback(object : OnPageChangeCallback(){
                          var oldPosition = 0
                          override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int
                          ) {
                              super.onPageScrolled(position, positionOffset, positionOffsetPixels)
                              if (position < oldPosition) {
                                  setCurrentItem(oldPosition, false)
                              } else {
                                  oldPosition = position
                              }
                          }
                      })
                  }
              

              【讨论】:

                【解决方案9】:

                您可以使用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
                   }
                }
                

                【讨论】:

                • 你在哪里设置 mCurrentPosition ?
                • 您可以将 mCurrentPosition 替换为 yourViewPager.getCurrentItem()
                • 不行,viewPager.getCurrentItem 改变 onRelease。
                猜你喜欢
                • 1970-01-01
                • 2015-12-03
                • 1970-01-01
                • 1970-01-01
                • 2023-03-05
                • 1970-01-01
                • 2013-11-05
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多