【问题标题】:How to scroll a Pager programatically AND smoothly如何以编程方式平滑滚动页面
【发布时间】:2014-09-14 13:21:24
【问题描述】:

我正在使用此代码以编程方式滚动我的寻呼机

public void MoveNext(View view) {
    pager.setCurrentItem(pager.getCurrentItem() + 1);
}

public void MovePrevious(View view) {

    pager.setCurrentItem(pager.getCurrentItem() - 1);

}

代码运行良好,但转换速度太快。如何引入延迟以使滚动更顺畅?

【问题讨论】:

    标签: android user-interface android-viewpager android-ui


    【解决方案1】:

    改变

    pager.setCurrentItem(pager.getCurrentItem() + 1);
    

    pager.setCurrentItem(pager.getCurrentItem() + 1,true);
    

    这将调用方法setCurrentItem(int item,boolean smoothScroll),它将平滑滚动到提到的item,而不是立即转换

    【讨论】:

      【解决方案2】:

      我相信有两种方法可以实现这个目标,我已经通过 ViewPager 的fakeDrag() 尝试过,但它并不完美,幸运的是,另一种方法可以,通过模拟触摸运动事件并使用 ObjectAnimator 指定动画持续时间然后使控制滚动速度变为真。

      public class ViewPagerActivity extends FragmentActivity
              implements View.OnClickListener, Animator.AnimatorListener {
      
          private ViewPager mViewPager;
          private View btnTriggerNext;
          private View btnTriggerPrev;
      
          @Override
          protected void onCreate(...) {
              super...;
              setContentView(R.layout.layout_xml);
      
              mViewPager = findViewById(...);
      
              btnTriggerNext = findViewById(R.id.btnTriggerNext);
              btnTriggerNext.setOnClickListener(this);
      
              btnTriggerPrev = findViewById(R.id.btnTriggerPrev);
              btnTriggerPrev.setOnClickListener(this);
          }
      
          private boolean mIsInAnimation;
          private long mMotionBeginTime;
          private float mLastMotionX;
      
          @Override
          public void onClick(View v) {
              if (mIsInAnimation) return;
              ObjectAnimator anim;
      
              if (v == btnTriggerPrev) {
                  if (!hasPrevPage()) return;
                  anim = ObjectAnimator.ofFloat(this, "motionX", 0, mViewPager.getWidth());
              }
              else if (v == btnTriggerNext) {
                  if (!hasNextPage()) return;
                  anim = ObjectAnimator.ofFloat(this, "motionX", 0, -mViewPager.getWidth());
              }
              else return;
      
              anim.setInterpolator(new LinearInterpolator());
              anim.addListener(this);
              anim.setDuration(300);
              anim.start();
          }
      
          public void setMotionX(float motionX) {
              if (!mIsInAnimation) return;
              mLastMotionX = motionX;
              final long time = SystemClock.uptimeMillis();
              simulate(MotionEvent.ACTION_MOVE, mMotionBeginTime, time);
          }
      
          @Override
          public void onAnimationEnd(Animator animation) {
              mIsInAnimation = false;
              final long time = SystemClock.uptimeMillis();
              simulate(MotionEvent.ACTION_UP, mMotionBeginTime, time);
          }
      
          @Override
          public void onAnimationStart(Animator animation) {
              mLastMotionX = 0;
              mIsInAnimation = true;
              final long time = SystemClock.uptimeMillis();
              simulate(MotionEvent.ACTION_DOWN, time, time);
              mMotionBeginTime = time;
          }
      
          // method from http://stackoverflow.com/a/11599282/1294681
          private void simulate(int action, long startTime, long endTime) {
              // specify the property for the two touch points
              MotionEvent.PointerProperties[] properties = new MotionEvent.PointerProperties[1];
              MotionEvent.PointerProperties pp = new MotionEvent.PointerProperties();
              pp.id = 0;
              pp.toolType = MotionEvent.TOOL_TYPE_FINGER;
      
              properties[0] = pp;
      
              // specify the coordinations of the two touch points
              // NOTE: you MUST set the pressure and size value, or it doesn't work
              MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[1];
              MotionEvent.PointerCoords pc = new MotionEvent.PointerCoords();
              pc.x = mLastMotionX;
              pc.pressure = 1;
              pc.size = 1;
              pointerCoords[0] = pc;
      
              final MotionEvent ev = MotionEvent.obtain(
                      startTime, endTime, action, 1, properties,
                      pointerCoords, 0,  0, 1, 1, 0, 0, 0, 0);
      
              mViewPager.dispatchTouchEvent(ev);
          }
      
          private boolean hasPrevPage() {
              return mViewPager.getCurrentItem() > 0;
          }
      
          private boolean hasNextPage() {
              return mViewPager.getCurrentItem() + 1 < mViewPager.getAdapter().getCount();
          }
      
          @Override
          public void onAnimationCancel(Animator animation) {
          }
      
          @Override
          public void onAnimationRepeat(Animator animation) {
          }
      }
      

      因为它是模拟触摸事件,所以请使用适当的持续时间(小于 600ms 会很好)进行滚动,当滚动进行时,放下手指会停止滚动并导致一些错误。

      【讨论】:

      • 谢谢,拯救了我的一天!
      猜你喜欢
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 2015-11-09
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      相关资源
      最近更新 更多