您的位置:首页 > 其它

滚来滚去,滚来滚去...Scroller完全解析

2016-03-02 15:48 148 查看
Scroller和OverScroller这两个类是AndroidUI框架下实现滚动效果最关键的类,ScrollView内部的实现也是使用的OverScroller,所以熟练的使用这两个类的相关API,可以让我们满足大部分的开发需求。

在View类里面,有两个和滚动相关的方法,scrollTo()和scrollBy:这两个方法可以实现View内容的移动,注意,是内容,不是位置!是移动,不是滚动!什么叫做内容呢?比如说一个TextView,如果使用scrollTo(),那么移动的是里面的文字,而不是位置,scrollBy()也是一样的。那么为什么是移动,不是滚动呢?这是因为这两个方法完成的都是瞬间完成,即瞬移,而不是带有滚动过程的滚动,所以说,如果要实现效果比较好的滚动,光靠View自带的方法还是不行滴,还是要Scrollers出马~

但是Scrollers并不是控制View进行滚动,包括内容或者位置,Scrollers只是一个控件移动轨迹的辅助计算类,如果你想滚,他能帮你计算什么时间应该滚到什么位置,但是滚不滚,全靠你自觉~所以说,滚动位置由Scrollers计算出来了,我们在什么时候滚呢?滚多少呢?这时候,就要View的一个回调函数computeScroll()出马了。

我们看看View里面的computeScroll()做了些什么

[java] view plain copy

/**

* Called by a parent to request that a child update its values for mScrollX

* and mScrollY if necessary. This will typically be done if the child is

* animating a scroll using a {@link android.widget.Scroller Scroller}

* object.

*/

public void computeScroll() {

}

duang!空的!不过没事,看看注释,就是说,如果我们用Scroller实现一个滚动动画的时候,这个方法就会被调用: 被谁调用呢?parent,谁改变呢?child。所以一般来说,这个方法可以用来更新mScrollX和mScrollY,但是其实不光可以改变这些,我们还能做其他事情。

如果我们调用Scroller.startScroll(int startX, int startY, int dx, int dy),那么我们就可以在computeScroll()里面执行实际的操作了,就像下面这样

[java] view plain copy

@Override

public void computeScroll() {

// 先判断mScroller滚动是否完成

if (mScroller.computeScrollOffset()) {

// 这里调用View的scrollTo()完成实际的滚动

scrollTo( mScroller.getCurrX(), mScroller .getCurrY());

// 必须调用该方法,否则不一定能看到滚动效果

invalidate();

}

super.computeScroll();

}

Scroller.computeScrollOffset方法是来判断滚动过程是否完成的,如果没有完成,就需要不停的scrollTo下去,所以在最后需要加一个invalidate(),这样可以再次触发computScroll,直到滚动已经结束。

其实说到这里,有的同学可能比较迷惑,OverScroller和Scroller有什么区别呢?

事实上,这两个类都属于Scrollers,Scroller出现的比较早,在API1就有了,OverScroller是在API9才添加上的,出现的比较晚,所以功能比较完善,Over的意思就是超出,即OverScroller提供了对超出滑动边界的情况的处理,这两个类80%的API是一致的,OverScroller比Scroller添加了一下几个方法

☞ isOverScrolled()
☞ springBack(int startX, int startY, int minX, int maxX, int minY, int maxY)
☞ fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY, int overX, int overY)
☞ notifyHorizontalEdgeReached(int startX, int finalX, int overX)
☞ notifyVerticalEdgeReached(int startY, int finalY, int overY)

从名字也能看出来,都是对Over功能的支持,其他的API都一样,所以介绍通用API的时候,并不区分OverScroller和Scroller。

下面简单介绍一下常用的API。

☞ computeScrollOffset() 这个就是来判断当前的滑动动作是否完成的,用法很单一,就是在computeScroll()里面来做判断滚动是否完成

☞ getCurrX(),getCurrY() 这个就是获取当前滑动的坐标值,因为Scrollers只是一个辅助计算类,所以如果我们想获取滑动时的时时坐标,就可以通过这个方法获得,然后在computeScroll()里面调用

☞ startScroll(int startX, int startY, int dx, int dy) 用来开始滚动,这个是很重要的一个触发computeScroll()的方法,调用这个方法之后,我们就可以在computeScroll里面获取滚动的信息,然后完成我们的需要。这个还有一个带有滚动持续时间的重载函数,可以根据需求自由使用。特别要注意这四个参数,startX和startY是开始的坐标位置,正数左上,负数右下,dx、dy同理,当在computeScroll()获取getCurrX()的时候,变化范围就与这里的设置有关。

☞ fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) 这个方法也很重要,如果你想实现滑动之后,布局能够根据移动速度,慢慢减速的话,就需要用这个来实现,这里需要加速度的参数,我们可以通过VelocityTracker这个类来获取,然后使用。

 ☞ getFinalX(),getFinalY() 这个是用来获取最终滑动停止时的坐标

☞ isFinished() 用来判断滚动是否结束

【参考资料】

滚来滚去,滚来滚去...Scroller相关类使用大揭秘!!! -- 赵凯强

Android Scroller完全解析,关于Scroller你所需知道的一切 -- 郭霖

Android 带你从源码的角度解析Scroller的滚动实现原理 -- 夏安明
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: