【问题标题】:Changing the speed of transition of ViewPager and setCurrentItem改变 ViewPager 和 setCurrentItem 的过渡速度
【发布时间】:2014-05-15 16:32:14
【问题描述】:

我有一个ViewPager,我想每 5 秒自动旋转一次,同时还允许用户滑动。但是,当我设置自动更改时,页面之间的过渡动​​画发生得非常快,我希望它慢一些。

我在这里看到了这个问题的答案:

Slowing speed of Viewpager controller in android

...但它们都使用反射。有谁知道在不使用反射的情况下减慢ViewPager 的自动速度的任何方法?

我想过使用PageTransformer,但不确定这是否可行,而且如果用户刷卡和自动刷卡一样,它可能会影响速度吗?除非我能以某种方式检测到差异,然后做一个或另一个PageTransformation

【问题讨论】:

    标签: android android-viewpager android-pagetransformer


    【解决方案1】:

    使用此自定义View

    public class ViewPagerCustomDuration extends ViewPager {
        private FixedSpeedScroller mScroller = null;
    
        public ViewPagerCustomDuration(Context context) {
            super(context);
            init();
        }
    
        public ViewPagerCustomDuration(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        /*
         * Override the Scroller instance with our own class so we can change the
         * duration
         */
        private void init() {
            try {
                Class<?> viewpager = ViewPager.class;
                Field scroller = viewpager.getDeclaredField("mScroller");
                scroller.setAccessible(true);
                mScroller = new FixedSpeedScroller(getContext(),
                        new DecelerateInterpolator());
                scroller.set(this, mScroller);
            } catch (Exception ignored) {
            }
        }
    
        /*
         * Set the factor by which the duration will change
         */
        public void setScrollDuration(int duration) {
            mScroller.setScrollDuration(duration);
        }
    
        private class FixedSpeedScroller extends Scroller {
    
            private int mDuration = 500;
    
            public FixedSpeedScroller(Context context) {
                super(context);
            }
    
            public FixedSpeedScroller(Context context, Interpolator interpolator) {
                super(context, interpolator);
            }
    
            public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
                super(context, interpolator, flywheel);
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy, int duration) {
                // Ignore received duration, use fixed one instead
                super.startScroll(startX, startY, dx, dy, mDuration);
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy) {
                // Ignore received duration, use fixed one instead
                super.startScroll(startX, startY, dx, dy, mDuration);
            }
    
            public void setScrollDuration(int duration) {
                mDuration = duration;
            }
        }
    }
    

    【讨论】:

    • 我实际上不记得我为什么问这个或者我是如何解决它的,但是这个答案已经足够了,我愿意接受它作为一个正确的答案。此外,@Ezio 似乎认为它有效:D
    • 优秀的解决方案。
    • 为什么至少对于 Compat 库中的组件不能进行调整?现在是 2018 年,我认为我们现在应该拥有自定义动画速度的能力......
    • @DenRimus 如此真实.. 难以置信。
    • @RussWheeler:在您的问题文本中,您明确要求没有反射的解决方案,并且该解决方案使用反射来访问私有字段。更糟糕的是,海报甚至懒得指出这一点。我认为你不应该接受这个答案。这个问题仍然有效且没有答案。
    【解决方案2】:

    您创建自定义视图寻呼机

    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.view.animation.Interpolator;
    import android.widget.Scroller;
    
    import java.lang.reflect.Field;
    
    public class CustomViewPager extends ViewPager {
    
        private FixedSpeedScroller mScroller = null;
        private boolean enabled;
    
        public CustomViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.enabled = true;
            init();
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (this.enabled) {
                return super.onTouchEvent(event);
            }
            init();
            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;
        }
    
    
        /*
         * Override the Scroller instance with our own class so we can change the
         * duration
         */
        private void init() {
            try {
                Class<?> viewpager = ViewPager.class;
                Field scroller = viewpager.getDeclaredField("mScroller");
                scroller.setAccessible(true);
                mScroller = new FixedSpeedScroller(getContext(),
                        new DecelerateInterpolator());
                scroller.set(this, mScroller);
            } catch (Exception ignored) {
            }
        }
    
        /*
         * Set the factor by which the duration will change
         */
        public void setScrollDuration(int duration) {
            mScroller.setScrollDuration(duration);
        }
    
        private class FixedSpeedScroller extends Scroller {
    
            private int mDuration = 500;
    
            public FixedSpeedScroller(Context context) {
                super(context);
            }
    
            public FixedSpeedScroller(Context context, Interpolator interpolator) {
                super(context, interpolator);
            }
    
            public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
                super(context, interpolator, flywheel);
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy, int duration) {
                // Ignore received duration, use fixed one instead
                super.startScroll(startX, startY, dx, dy, mDuration);
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy) {
                // Ignore received duration, use fixed one instead
                super.startScroll(startX, startY, dx, dy, mDuration);
            }
    
            public void setScrollDuration(int duration) {
                mDuration = duration;
            }
        }
    
    }
    

    你可以根据你的设置查看寻呼机的持续时间

    【讨论】:

      【解决方案3】:

      使用计划计时器选项自动旋转页面。

      int i = 0;
      static Timer timer = new Timer();
      
      //Scroller scroll = new Scroller(this);
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
      
          super.onCreate(savedInstanceState);
      
          setContentView(R.layout.simple_circles);
      
          mAdapter = new TestFragmentAdapter(getSupportFragmentManager());
      
          mPager = (ViewPager) findViewById(R.id.pager);
      
          mPager.setAdapter(mAdapter);
      
           mIndicator = (CirclePageIndicator) findViewById(R.id.indicator);
      
          mIndicator.setViewPager(mPager);
      
          mPager.setCurrentItem(i);
      
          SwitchPage(3);
      
      
        }
      
      public void SwitchPage(int seconds) 
      

      {

      if(timer != null)
      {
          timer.cancel();
      }
      
      timer = new Timer(); // At this line a new Thread will be created
      
      timer.schedule(new SwitchPageTask(), 
      2000, seconds * 2000);               
       // delay in milliseconds
       }
      
      
      class SwitchPageTask extends TimerTask 
      {
      
      @Override
      public void run() {
      
          runOnUiThread(new Runnable() {
      
              public void run() {
      
                  if(i < mAdapter.getCount())
      
                  {
      
                      i++;
      
                      mPager.setCurrentItem(i, true);
      
                  }
                  else
                  {
      
                      i=0;
      
                      mPager.setCurrentItem(i, true);
                  }
              }
          });
      }
      }
      
      just cancel the timer like.. timer.cancel().. or
      cancel timer from another activity or fragment activity..
      
          textView1_page3.setOnClickListener(new OnClickListener() {
      
                  @Override
                  public void onClick(View v) {
      
                      if (SampleCirclesDefault.timer != null) {
                          SampleCirclesDefault.timer.cancel();
                          Toast.makeText(getActivity(), "timer
                        cancled", 1).show();
                      }
      
                  }
              });
      

      【讨论】:

      • harikrishnan 查看您的代码,看起来您更改了更改之间的延迟。那不是我有问题的地方。我认为自动转换的实际动画太快了,几乎是即时的,我希望它从一个图像滚动到下一个图像,速度较慢,而不是在可变的时间差。我将更新我的原始问题以使其更清楚。
      猜你喜欢
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      相关资源
      最近更新 更多