从数字滚动动画看自定义View的绘制思路

前言

本篇文章是AndroidMsky的投稿,本篇文章主要讲解了对一个自定义View的实现,效果并不复杂,但是思路却很清晰,而且总结的很详细,相信会对不少开发者有帮助,希望大家多多学习。

另外,昨天在拍婚纱,有个活动,需要120个祝福,我老婆说,要这么多呀,我说,分分钟就搞定,刚发没多久,就凑齐了,非常感谢大家的祝福~也让我成功在老婆面前装了个逼,所以,非常感谢大家,后面一定多写好的文章来感谢大家~

最近在掘金这个干货平台上发了几篇博文,看掘金APP中文章数据的数字滚动起来很动感,效果很棒,

于是,我决定把它通过自定义View编写出来,方便自己和大家调用。

本文Github代码链接 https://github.com/AndroidMsky/RandomTextView

先看看掘金的效果:

我们自己实现的效果:

接下来介绍一下我的自定义View RandomTextView的用法和原理

用法

考入

RandomTextView.java

只有200行绝对轻量方便。代码可以参考Github,这里就不复制了。

xml中定义:

很开心的是,RandomTextView继承自TextView所以可以使用TextView的所有方法。color,size等等直接去定义就OK啦。

所有位数相同速度滚动:

从左到右侧由快到慢滚动:

从左到右侧由慢到快滚动:

自定义每位数字的速度滚动(每帧滚动的像素):

自定义滚动行数(默认10行):

mRandomTextView.setMaxLine(20);

原理

用TextView去绘制10(maxLine可设置)行文字,调用canvas.drawText去绘制出来,在绘制的Y坐标不断增加偏移量,去改变绘制的高度,通过handler.postDelayed(this, 20);不断增加偏移量,并且不断判断所有位数字最后一行绘制完毕的时候,结束handler的循环调用。

第一次进入onDraw方法时,做了如下几件事情: 1.去获取当前正确的画笔p = getPaint();从而保证xml中配置的大小颜色等有效。 2.通过当前画笔去计算正确的drawText基准线。 baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top; 3.等到数字的宽度。方便横向绘制。 p.getTextWidths(“9999”, widths);f0 = widths[0]; 4.直接通知view重绘。 invalidate();

我们自己的绘制drawNumber方法:

这里逻辑想对复杂时间复杂度达到了O(绘制行数*字符串位数),是个双重循环的绘制。

第一层我们称之为J循环,J循环每次循环的内容是绘制一列。

第二层循环称之为I循环,I循环负责绘制每行的每一个字符。

每次进入I循环的第一件事情是检查当前字符位,是不是最后一个

如果是,则归零偏移量,修改标志位

pianyilianglist[j] = 0;
overLine[j] = 1;

之后去判段所有字符位是否全部绘制到最后一个:

如果是则讲自动循环刷新的方法取消掉,并且通知view进行最后一次定位绘制。

以上就是进入i循环先对是否绘制结束的判断。

如果没有结束那么继续绘制。

overLine[j]中的值的意思为:0表示还没绘制到最后一行,1表示为绘制到最后一行没有进行最后的定位绘制,2表示已经进行了定位绘制。

可能对于初学者最难的就是drawText的坐标问题,x坐标比较简单,就是字符的宽度并且随着循环去变化:

0 + f0 * j

Y坐标就是当前行的基准值+上当前偏移量:

i * baseline + pianyiliangSum[j]

我们还需要几个辅助的方法:

1.每隔20毫秒去计算当前偏移量并通知刷新。 2.帮助计算9上面的是几。8上面是几。 3.将字符串转换为INT数组。 4.通过Handler控制重绘。

我们还需要几个供给用户调用的方法: 1.start开始滚动。 2.设置滚动行数maxline。 3.设置偏移量速度数组。 4.可能用户不希望每次都设置偏移量数组那么我们提供三种默认的偏移量速度数组(高位快,高位慢,速度相同)

回顾

在自定义view的时候如果你的view是像本文一样,循环去绘制不断刷新的话,就意味着onDraw方法会随着你view的帧数不断的被调用,一秒可能被执行几十次。 所以写在这里的方法,一定要小心为妙,比如一些无需每次都初始化的变量切记不可以定义在onDraw方法里。 比如本文的getText();方法去获取当前TextView的内容,就要写在外面。 但是可能有些方法你必须在super.onDraw(canvas),以后才可以获取的比如getPaint();那么我们就可以加个布尔值firstIn来控制只有第一次进入onDraw方法才去执行,或者其它的只做一次的事情都可以这样去控制。

循环绘制动画效果我们一定要理清两条线,一条是每一帧绘制什么,另一条是动画结束你都绘制了什么。

第一条线应该注意你绘制的只是一个瞬间,是个不断重复执行的线。

第二条线就是无数个第一条线加上时间点共同组成的,主要就是控制每次的不同,比如本文中增加的偏移量,是数据(本文中每一个字符的坐标)的变化,去影响onDraw方法,绘制出不通的东西呈现在屏幕上。第二条线还要控制好什么时候结束所有的第一条线,也就是整个动画结束的条件,本文中的例子讲是一旦所有字符的最后一行都超过或者等于TextView的基准线,那么整个动画结束。

绘制原理的逻辑就讲完啦,RandomTextView可以投入使用啦,自定义view并不难,只要你知道安卓API能让你能干什么,你想干什么,你可能马上就知道你应该怎么做啦。

欢迎关注作者。欢迎评论讨论。欢迎拍砖。

原文发布于微信公众号 - Android群英传(android_heroes)

原文发表时间:2016-11-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏竹清助手

jQuery架构设计与实现(2.1.4版本)

1384
来自专栏大前端_Web

前端开发常用函数及小技巧(持续更新)

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

2003
来自专栏阮一峰的网络日志

jQuery最佳实践

上周,我整理了《jQuery设计思想》。 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery"。今天的文章则是更进一步,讲解"如何用好jQue...

3716
来自专栏数据科学学习手札

(数据科学学习手札41)folium基础内容介绍

  folium是js上著名的地理信息可视化库leaflet.js为Python提供的接口,通过它,我们可以通过在Python端编写代码操纵数据,来调用leaf...

6627
来自专栏新工科课程建设探讨——以能源与动力工程专业为例

2.2.3 文档对象模型DOM及表单

文档对象模型DOM用途是什么?先从一棵树说起。下面是一棵树,由,根部、枝干、叶构成,通过根部可以访问到任何一个叶节点。

702
来自专栏全沾开发(huā)

总结CSS3新特性(选择器篇)

总结CSS3新特性(选择器篇) CSS3新增了 ? 嗯- -21个选择器,脚本通过控制台在这里运...

2924
来自专栏用户2442861的专栏

javascript dom学习笔记

http://blog.csdn.net/zhoulenihao/article/details/11099455

1161
来自专栏jiajia_deng

设置 Notepad++ 制表符(Tab 缩进)宽度为2个空格大小

1382
来自专栏郭少华

(第一季)Vue2.0-内部指令

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核...

1143
来自专栏知道一点点

bootstrap快速入门笔记(六)-代码

一,内联代码<code>:For example, <code>&lt;section&gt;</code> should be wrapped as inli...

822

扫码关注云+社区

领取腾讯云代金券