前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从数字滚动动画看自定义View的绘制思路

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

作者头像
用户1907613
发布2018-07-20 15:35:26
2.7K0
发布2018-07-20 15:35:26
举报
文章被收录于专栏:Android群英传

前言

本篇文章是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行):

代码语言:javascript
复制
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循环的第一件事情是检查当前字符位,是不是最后一个

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

代码语言:javascript
复制
pianyilianglist[j] = 0;
overLine[j] = 1;

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

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

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

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

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

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

代码语言:javascript
复制
0 + f0 * j

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

代码语言:javascript
复制
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能让你能干什么,你想干什么,你可能马上就知道你应该怎么做啦。

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 群英传 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用法
  • 原理
  • 回顾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档