理解Scroller

Posted hixin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解Scroller相关的知识,希望对你有一定的参考价值。

任何一个控件都是可以滚动的,因为在View类当中有scrollTo()和scrollBy()这两个方法,但使用这两个方法完成的滚动效果是跳跃式的,没有任何平滑滚动的效果.而Scroller正是实现平滑滚动的利器

Android Scroller完全解析

View滑动的若干方法

startScroll方法

对于Scroller的startScroll 方法一直不太理解

startScroll

added in API level 9
public void startScroll (int startX, 
                int startY, 
                int dx, 
                int dy)
Start scrolling by providing a starting point and the distance to travel. The scroll will use the default value of 250 milliseconds for the duration.

Parameters
startX	int: Starting horizontal scroll offset in pixels. Positive numbers will scroll the content to the left.
startY	int: Starting vertical scroll offset in pixels. Positive numbers will scroll the content up.
dx	int: Horizontal distance to travel. Positive numbers will scroll the content to the left.
dy	int: Vertical distance to travel. Positive numbers will scroll the content up.

例子: 点击Button实现平滑滚动

public class ScrollerButton extends Button {
    private OverScroller mScroller;

    public ScrollerButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        mScroller = new OverScroller(context);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }

    public void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        mScroller.startScroll(scrollX, 0, delta, 0, 2000);
        invalidate();
    }
}

----
调用部分:
scrollToBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        layout.scrollTo(-60, 0);
    }
});

smoothScrollToBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        smoothScrollToBtn.smoothScrollTo(-60, 0);
    }
});

由于滚动都是针对内容,要想实现Button整体移动, computeScroll中要调用其父控件的scrollTo方法

  • 比较奇怪是,第一次点击, Butoon两秒后向右移动到60位置
  • 再次点击,又重复这个动作,先向左回到0,再向右回到 60 -> 0 -> 60

为什么会这样呢, 原来是getScrollX()在捣鬼, Button始终没有执行过ScroolTo和ScroolBy方法, 所以getScrollX始终为0. 所以一直重复 0 到 -60

论startScroll的正确用法

 public void smoothScrollTo(int destX, int destY) {
        int scrollX = ((View) getParent()).getScrollX();
        Log.i(TAG, "smoothScrollTo: " + scrollX);
        mScroller.startScroll(scrollX, 0, destX - scrollX, 0, 2000);
        invalidate();
    }
  • 第一个参数的要写getScrollX(), 避免上面的奇怪现象
  • 第三个参数要减去scrollX, 这样可以保证滑到指定位置就不滑了, 否则回出现始终滑动的问题.
  void startScroll(int start, int distance, int duration) {
            mFinished = false;

            mCurrentPosition = mStart = start;
            mFinal = start + distance;

            mStartTime = AnimationUtils.currentAnimationTimeMillis();
            mDuration = duration;

            // Unused
            mDeceleration = 0.0f;
            mVelocity = 0;
        }

以上是关于理解Scroller的主要内容,如果未能解决你的问题,请参考以下文章

Android源码解析Scroller

vux scroller 向上刷新加载数据

Android 仿 窗帘效果 和 登录界面拖动效果 (Scroller类的应用) 附 2个DEMO及源代码

使用Scroller制作滑块开关ToggleButton

vue-scroller记录滚动位置的示例代码

金蝶handler中 collection 代码片段理解