博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从源码分析scrollTo、scrollBy、Scroller方法的区别和作用
阅读量:6262 次
发布时间:2019-06-22

本文共 2803 字,大约阅读时间需要 9 分钟。

目    录(本篇字数:1201)


  • 介绍

    今天,我们来讲讲自定义View的基本功,那就是对我们屏幕坐标系的理解。本人画了一张图,咋们凑合看吧,应该不难看懂。

    这里做略微的说明,黑色(ViewGroup、父容器)、蓝色(包含的子View)、橙色为手指触摸屏幕的一点。为什么要清楚这张图呢?因为在自定义View中经常出现这几个方法,想必你不熟悉的话,可能看代码的时候就会一头雾水!

    熟悉完之后,我们来了解一下视图滚动的几个重要方法,下面我来看一张动态图,相信你看完已经明白了scrollTo、scrollBy是怎么一回事了。

  • 测试图

  • 区别分析

  • scrollTo

    请仔细看完上面的动态图,你会发现scrollTo和scrollBy的区别了。我这里简单的说明一下scrollTo和scrollBy的区别。

    scrollTo(int x,int y),这是一个以坐标点为目的的滚动,指定它所移动的坐标位置,但如果重复移动的坐标未发生改变,你只能看到一次移动效果。

    scrollTo的源码分析:这个函数不难看出,当我们传入x,y时,它会与view之前所处的位置进行比较,如果坐标相同的话,将不会产生滚动。如果坐标不同,它内部会调用onScrollChanged()去滚动视图。

/**     * Set the scrolled position of your view. This will cause a call to     * {@link #onScrollChanged(int, int, int, int)} and the view will be     * invalidated.     * @param x the x position to scroll to     * @param y the y position to scroll to     */    public void scrollTo(int x, int y) {        if (mScrollX != x || mScrollY != y) {            int oldX = mScrollX;            int oldY = mScrollY;            mScrollX = x;            mScrollY = y;            invalidateParentCaches();            onScrollChanged(mScrollX, mScrollY, oldX, oldY);            if (!awakenScrollBars()) {                postInvalidateOnAnimation();            }        }    }
  • scrollBy

    scrollBy(int disX,int disY),这是一个以偏移量为目的滚动,指定它所移动的偏移量,既然是偏移量便可以多次看到移动效果。

    scrollBy源码:它内部是调用scrollTo()方法来实现自身的滚动的。不难看出它是根据当前的坐标加上目标移动的坐标,除非你传入 0 ,否则它始终会产生滚动效果。

/**     * Move the scrolled position of your view. This will cause a call to     * {@link #onScrollChanged(int, int, int, int)} and the view will be     * invalidated.     * @param x the amount of pixels to scroll by horizontally     * @param y the amount of pixels to scroll by vertically     */    public void scrollBy(int x, int y) {        scrollTo(mScrollX + x, mScrollY + y);    }
  • Scroller

   无论是scrollTo或scrollBy,你会发现往左移动时,例如scrollBy(20,0),它的x轴坐标是正的,但它却是往左移动。如上图我们的坐标系x轴右边才是增加吗?那它上面又会往左移动呢?

   其实,这个是这样理解的。因为它对应的参考系不同,比如对于子View来说,它想把右边屏幕外的一个物体移动到屏幕内显示,那手势应该是从右往左滑动。对于子View的坐标而言,右边View的坐标一定比左边View的大,所以scrollBy(20,0)里面的X坐标只有增加时才能显示出右边,那么当前子View则只能是左移了。这个比较抽象,理解起来不容易。

    那么接下来我们看看Scroller这个类,其实它与scrollTo和scrollBy类似的效果。这个Scroller类封装了一些滚动行为,可想而知功能上肯定丰富了许多。它的基本使用方式:

private Scroller mScroller;private void init(){    mScroller = new Scroller(context);}/*** startX ,startY 起始的x,y坐标* dx ,dy 滚动距离*/private void scroll(){    mScroller.startScroll(int startX, int startY, int dx, int dy);    postInvalidate();}@Overridepublic void computeScroll() {    super.computeScroll();    if (mScroller.computeScrollOffset()) {        scrollTo(x, y);        postInvalidate();    }}

    它的滚动也是一瞬间就完成的,这样看起来滚动效果会特别生硬。于是,我们可以覆盖它的computeScroll()方法。在postInvalidate()是会调用onDraw()、computeScroll()方法,然后在computeScroll()里判断滚动是否已经结束,如果还未结束,我们可以继续滚动它。例如,在一定距离和规定时间内完成它的多次分解滚动动作,将多次滚动串在一起形成一次平滑的滚动,效果将大大提升。

©原文链接:

@作者博客:

@更多博文:

转载于:https://www.cnblogs.com/xww0826/p/10359505.html

你可能感兴趣的文章
json \u unicode字符串转化 c++
查看>>
WinDbg 调试工具的使用
查看>>
最全linux命令
查看>>
Jexus部署.Net Core项目
查看>>
tomcat设置
查看>>
第十二单元 不同系统之间的文件传输
查看>>
安装mysql报错,错误提示:Incorrect definition of table mysql.proc
查看>>
网吧维护工具
查看>>
BOOT.INI文件参数
查看>>
Exchange-批量创建通讯组邮箱
查看>>
系统目录结构、ls命令、文件类型、alias命令
查看>>
win10 uwp 异步转同步
查看>>
简单CDN之智能DNS
查看>>
UPS工作模式简析
查看>>
词向量-LRWE模型
查看>>
Selenium打包成exe运行出错
查看>>
shell脚本之重定向、标准输入、输出、错误输出的使用
查看>>
如何从Google官网下载Chrome离线安装包
查看>>
JAR——CircleImageView
查看>>
Centos6.5下rsync文件同步安装及配置当中遇到的问题及解决方法
查看>>