文档章节

View的滚动以及Scroller探究

飞越围墙
 飞越围墙
发布于 2016/11/13 17:34
字数 909
阅读 12
收藏 0
点赞 0
评论 0

前言

说来惭愧,Android开发好几年,对于滚动仍然一无所知,一般自定义view如果要滚动就是直接把ScrollView也打包进去,也能完成既定需求.在公司项目中有一个环形菜单控件一直点卡卡的,看代码是响应触摸事件然后改变LayoutParams,再重绘实现的,当时想这个也相当于"滑动"呀,是不是可以用Scroller来实现(后来发现太天真).

Scroller

Scroller是一个滚动的辅助类,它负责告诉你某一时刻滚动到了那个位置以及滚动有没有完成. 下面是几个主要的方法

  • void startScroll(int startX, int startY, int dx, int dy, int duration) 开始滚动,Scroller纪录开始的位置,要滚动的距离,滚动时间,以及滚动开始的时刻
  • boolean computeScrollOffset() 计算滚动距离,Scroller计算调用这个方法的时刻需要滚动到的位置,顺便返回是否已经滚动到位了(即结束了)
  • int getCurrX() 方法调用时刻scroller的X位置
  • int getCurrY() 方法调用时刻scroller的Y位置

假如:我自定义View的内容要移动水平移动50,垂直移动30,是怎样进行的呢

  1. 先startScroll,纪录下要从0,0,X滚动50,Y滚动30,滚动时间250ms
  2. 调用computeScrollOffset()计算一下从startScroll开始到现在过了多少时间,按速度应该到哪个位置了.
  3. 用getCurrX()和getCurrY()拿到计算出来的位置,把View的内容移到那个位置
  4. 要是第2步的computeScrollOffset()返回true,则再调用第2步,循环往复,直到返回false,说明移动到位了,滚动结束

View的滚动

View的滚动就是按上面的原理进行的, 首先我们通过事件(滑动,点击,代码)触发滚动,调用startScroll,然后调用postInvalidate()重绘View, 重绘会调用View.computeScroll(),这个方法里调用上面说的第2-3步(这里最后移动内容是调用的View.scrollTo(x,y)), 而scrollTo又会触发View的重绘,循环往复,直到滚动完成.

真正移动view的内容的动作是View.scrollTo(x,y),通过分析源代码发现是通过移动canvas来实现的.

代码比文字简单100倍,

测试代码片段:http://git.oschina.net/sun141421/laj4tp78vcr12usw36ghd69.code.git

以下是对View的源代码不严谨分析(基于Android-24)

View.scrollTo(x,y)

  /**
     * 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();
            }
        }
    }

可以看出它只是赋值了mScrollX mScrollY,并调用postInvalidateOnAnimation()引起View树的重绘, 父控件通过调用viewGroup.drawChild()重绘子控件

    /**
     * Draw one child of this View Group. This method is responsible for getting
     * the canvas in the right state. This includes clipping, translating so
     * that the child's scrolled origin is at 0, 0, and applying any animation
     * transformations.
     *
     * @param canvas The canvas on which to draw the child
     * @param child Who to draw
     * @param drawingTime The time at which draw is occurring
     * @return True if an invalidate() was issued
     */
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
    }

子控件的 child.draw(canvas, this, drawingTime)中调用了updateDisplayListIfDirty();

     /**
     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
     *
     * This is where the View specializes rendering behavior based on layer type,
     * and hardware acceleration.
     */
    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
        ....
        renderNode = updateDisplayListIfDirty();
        ....            
    }

在updateDisplayListIfDirty()中有关键的几行,

    /**
     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
     * @hide
     */
    @NonNull
    public RenderNode updateDisplayListIfDirty() {
        ....
         computeScroll();

         canvas.translate(-mScrollX, -mScrollY);
        ....  
       draw(canvas);
        ....
            
    }

它先调用 computeScroll()计算好mScrollX,mScrollY然后 canvas.translate,最后draw

© 著作权归作者所有

共有 人打赏支持
飞越围墙
粉丝 1
博文 2
码字总数 909
作品 0
广州
程序员
源码解析---Scroller完全解析

Scroller完全解析 1.概述 Scroller是一个专门用于处理滚动效果的工具类,可能在大多数情况下,我们直接使用Scroller的场景并不多,但是很多大家所熟知的控件在内部都是使用Scroller来实现的,...

android-key ⋅ 2016/11/23 ⋅ 0

Scroller和OverScroller

一、ViewDragHelper 二、OverScroller 参考ScrollView

GalaxyBruce ⋅ 2016/06/17 ⋅ 0

Android Scroller类与computeScroll方法的调用关系

Android ViewGroup中的Scroller与computeScroll的有什么关系? 答:没有直接的关系 知道了答案,是不是意味着下文就没必要看了,如果说对ViewGroup自定义控件不感兴趣,可以不用看了。 1.Sc...

IamOkay ⋅ 2016/01/10 ⋅ 3

android 中文 api (64) —— Scroller

前言   本章内容是 android.widget.Scroller,版本为Android 2.3 r1,翻译来自"pengyouhong",再次感谢"pengyouhong"!期待你一起参与Android中文API的翻译,联系我over140@gmail.com。 声...

会飞柚子 ⋅ 2015/11/24 ⋅ 0

Android 带你从源码的角度解析Scroller的滚动实现原理

转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273),请尊重他人的辛勤劳动成果,谢谢! 今天给大家讲解的是Scroller类的滚动实现原理,可能很...

程序袁_绪龙 ⋅ 2015/08/13 ⋅ 0

Android 中 scrollTo | scrollBy | Scroller 的使用

Android Scroller完全解析,关于Scroller你所需知道的一切 本文基于郭神给出的教程(原文地址如上),在结合自己的编码总结这个几个东西的使用。 先来说 scrollTo()与scrollBy()的使用与区别...

a_zhon ⋅ 2017/12/27 ⋅ 0

Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果

转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17539199),请尊重他人的辛勤劳动成果,谢谢! 我在上一篇文章中Android 带你从源码的角度解析Scrol...

程序袁_绪龙 ⋅ 2015/08/13 ⋅ 0

Scroller在ListView中滑动不良问题

各位大侠: 小弟在ListView中放置了若干个 “自定义的水平滚动控件”。 listView全屏。 在上下左右滑动中(全方位),ListView能正常的上下滑动。但是水平容器中放置的View存在5%可能不会跟着...

Carlyle_Lee ⋅ 2013/01/30 ⋅ 0

站在源码的角度全解Scroller工作机制(三)

现在,已经对scrollTo()和scrollBy()这两个方法有了基本的了解,我们再看看它们的用法。 在这个示例中对TextView分别调用scrollTo( )和scrollBy( ),代码如下: 当我们调用scrollBy()时,Tex...

博为峰教研组 ⋅ 2016/11/24 ⋅ 0

android scroller的原理分析

谷歌为什么要设计一个scroller? 在Android中所有的的View都有一个实际界面大于可视界面的,这就涉及到界面的移动或者说偏移,View这个类提供了scrollTo和ScrollBy方法来实现界面的滚动,但是...

博为峰教研组 ⋅ 2016/10/28 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

对于程序员的招聘问题,作为软件人的一些吐槽和建议

作为软件人,找工作有时候似乎挺苦逼的。 说真的,让我去掉前面这句中“似乎”二字吧。就是苦逼!很多人都曾抱怨处在招聘的一方很糟糕——我们没有任何可靠的方式来甄别会写代码并且写得好的...

老道士 ⋅ 8分钟前 ⋅ 0

HDFS原理学习

一、概述 1、 Hadoop整合了众多的文件系统,首先提供了一个高层的文件系统抽象org.apache.hadoop.fs.FileSystem。然后有各个文件系统的实现类。 2、Hadoop是JAVA编写的,不同文件系统之间的交...

cjxcloud ⋅ 12分钟前 ⋅ 0

Linux下MySQL表名不区分大小写的设置方法(抄袭别人的)

Linux下MySQL表名不区分大小写的设置方法 MySQL表名不区分大小写的设置方法 在用centox安装mysql后,把项目的数据库移植了过去,发现一些表的数据查不到,排查了一下问题,最后发现是表名的大...

随风而浮沉 ⋅ 17分钟前 ⋅ 0

ubuntu下安装宋体simsun

sudo cp simsun.ttc /usr/share/fonts cd /usr/share/fonts sudo chmod 644 simsun.ttc 更新字体缓存: 代码: sudo mkfontscale 代码: sudo mkfontdir 代码: sudo fc-cache -fsv 安装chrome扩......

wangxuwei ⋅ 19分钟前 ⋅ 0

利用 ssh 传输文件

Linux 下一般可以用 scp 命令通过 ssh 传送文件: #把服务器上的 /home/user/a.txt 发送到本机的 /var/www/local_dir 目录下scp username@servername:/home/user/a.txt /var/www/local_dir...

大灰狼时间 ⋅ 29分钟前 ⋅ 0

web3j教程:android和java程序员如何使用web3j开发区块链以太坊

如何使用web3j为Java应用或Android App增加以太坊区块链支持,本教程内容即涉及以太坊中的核心概念,例如账户管理包括账户的创建、钱包创建、交易转账,交易与状态、智能合约开发与交互、过滤...

智能合约 ⋅ 51分钟前 ⋅ 0

web3j开发java或android以太坊智能合约快速入门

web3j简介 web3j是一个轻量级、高度模块化、响应式、类型安全的Java和Android类库提供丰富API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成。 可以通过它进行以太坊区块链...

笔阁 ⋅ 53分钟前 ⋅ 0

一起读书《深入浅出nodejs》-异步I/O

异步I/O “异步”这个名词其实很早就诞生了,但它大规模流行却是在Web 2.0浪潮中,它伴随着AJAX的第一个A(Asynchronous)席卷了Web。 为什么要异步I/O 关于异步I/O为何在Node里如此重要,这与...

小草先森 ⋅ 56分钟前 ⋅ 0

JVM各种问题

1、如果启动什么都不设,会怎样? 先来看一个命令 [root@localhost bin]# java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=29899008 -XX:MaxHeapSize=478384128 -XX:+PrintCo......

算法之名 ⋅ 今天 ⋅ 0

SAS笔记-宏2

宏是一种文本,一般来说其编译是在程序执行之前。 宏变量的创建 %let语句 %let macro_variables = text; %let是常见的宏变量建立方式,其编译就在执行前。如下例中,想要宏变量test等于数据集...

tonorth123 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部