View的事件体系---V3.3 弹性滑动

一. 在上一节中,讲述了View滑动的三种方式,如果直接使用呢,会显得比较生硬,用户体验不太好,下面简单描述一下实现View的渐进式滑动。实现方式挺多,大致原理都是一样的,将一次大的滑动划分成若干次小的滑动,并在一个时间段内完成,下面简单介绍三种:

a. Scroller

b. Handler#postDelayed

c. Thread#Sleep

二. 使用Scroller

a. 简述一下这个的实现原理和代码

<span style="font-family:KaiTi_GB2312;">private void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int scrollY = getScrollY();
        mScroller.startScroll(scrollX, scrollY, destX, destY);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }</span>

上面是Scroller的典型的使用方法,当我们构造一个Scroller对象并调用它的startScroll方法时,Scroller内容其实什么也没做,只是保存了我们传递的几个参数,源码如下:

<span style="font-family:KaiTi_GB2312;">/**
     * Start scrolling by providing a starting point, the distance to travel,
     * and the duration of the scroll.
     * 
     * @param startX Starting horizontal scroll offset in pixels. Positive
     *        numbers will scroll the content to the left.
     * @param startY Starting vertical scroll offset in pixels. Positive numbers
     *        will scroll the content up.
     * @param dx Horizontal distance to travel. Positive numbers will scroll the
     *        content to the left.
     * @param dy Vertical distance to travel. Positive numbers will scroll the
     *        content up.
     * @param duration Duration of the scroll in milliseconds.
     */
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        mMode = SCROLL_MODE;
        mFinished = false;
        mDuration = duration;
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;
        mStartY = startY;
        mFinalX = startX + dx;
        mFinalY = startY + dy;
        mDeltaX = dx;
        mDeltaY = dy;
        mDurationReciprocal = 1.0f / (float) mDuration;
    }</span>

startX startY表示滑动的起点,dx dy表示滑动的距离,duration表示的滑动的时间。startScroll之后的invalidate方法会导致view重绘,在View的onDraw方法中又会调用computeScroll方法,此方法内部调用ScrollTo方法进行滑动,同时又调用postInvalidate方法通知到View进行重绘,反复如此,完成View的弹性滑动,ps:此时完成的是View内容的滑动而非view本身的滑动。

三. 通过动画

a. 动画本身就是一种渐进的过程,通过他实现的滑动自然具有滑动效果。

b. 示例代码如下:将parent对象,在1S内右移100个像素。

<span style="font-family:KaiTi_GB2312;">ObjectAnimator.ofInt(parent, "translationX", 0, 100).setDuration(1000).start();</span>

c. 下面利用ValueAnimator结合Scroller来实现View的滑动,代码如下:

<span style="font-family:KaiTi_GB2312;">public void onAnimScroll(View view) {
        final int startX = 0;
        final int delaX = 100;
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1).setDuration(100);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedFraction = (int) animation.getAnimatedFraction();
                parent.scrollTo(startX + (int) (animatedFraction * delaX), 0);
            }
        });
        valueAnimator.start();
    }</span>

四. 使用延时策略

a. 核心思想是通过发送一系列延时消息达到一种渐进式的效果,比如Handler或View的postDelayed方法,或者使用线程的sleep方法。

b. 对于postDelay方法来说,通过发送延时消息,在消息中进行View的滑动处理。

c. 对于sleep,通过while循环中不断地滑动View和sleep,就可以实现滑动效果。

d. 下面使用handler来实现View的弹性滑动,代码如下:

<span style="font-family:KaiTi_GB2312;">private static final int MESSAGE_SCROLL_TO = 3;
    private static final int FRAME_COUNT = 33;
    private static final int DELAYED_TIME = 30;

    private int mCount;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_SCROLL_TO:
                    mCount++;
                    if (mCount <= FRAME_COUNT) {
                        float fraction = mCount / (float) FRAME_COUNT;
                        int scrollX = (int) (fraction * 100);
                        parent.scrollTo(scrollX, 0);
                        mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME);
                    }
                    break;
            }
        }
    };

    public void onHandleScroll(View view) {
        mHandler.sendEmptyMessageDelayed(MESSAGE_SCROLL_TO, DELAYED_TIME);
    }</span>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值