如何以编程方式流畅地滚动寻呼机

Lib*_*hos 2 user-interface android android-ui android-viewpager

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

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

public void MovePrevious(View view) {

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

}
Run Code Online (Sandbox Code Playgroud)

代码工作完美,但过渡太快。如何引入延迟以便滚动更顺畅?

Vin*_*ing 5

I believe there are two ways can achieve this goal, I've tried by ViewPager's fakeDrag() but which doesn't work perfect, luckly, another way does, by simulate touch motion event and use ObjectAnimator to specify the animation duration then make control the scroll speed become true.

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) {
    }
}
Run Code Online (Sandbox Code Playgroud)

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