歌词显示控件的实现(下)——自定义View

先看下效果

在上篇文章中呢,分享了关于lrc歌词文件的解析方法,根据歌词文件格式,解析出对应实体类。但是,怎样才能让让自己的音乐播放器的歌词像网易云音乐一样,随音乐(歌词时间)滚动、当前歌词高亮、其他歌词渐变等效果呢?

接下来我想和大家分享的就是如何通过自定义View实现炫酷的LyricView歌词显示控件。

01

分析

我们最重要的目的是将文字绘制在View中,并设置各种效果和动画,而在绘制之前我们需要计算出文字的位置,而歌词又是以 为单位来显示,所以,计算行高和行间距,当然,还需要一些文字颜色等属性;

可以想到,歌词会随着音乐或者说时间进行滚动,所以我们需要对纵向偏移量进行计算和处理,并设置滚动动画;

接下来就应该逐行进行绘制了,之后可以给当前播放位置绘制指示器以提高逼格

用户可以手势滑动歌词进行查看,之后还需要回滚,所以我们需要对手势,也就是onTouchEvent进行处理。

好的,大致思路就是这样,接下来我们一步步地实现:

02

解析歌词,设置实体类

解析歌词上一篇文章已经介绍很详细,这里不再累赘。

这里讲歌词解析也封装进LyricView中,所以解析与赋值一并进行。

注意赋值实体类时,View其实已经绘制过了,不过界面上什么都没有显示(因为LyricInfo类为null,在绘制时会返回不再继续),赋值实体类后,在刷新一下界面:

在这里进行线程的判断,主线程中直接调用invalidate,在子线程中调用postInvalidate,原因想必大家都清楚,就不再解释了。

03

设置大小、颜色等属性

其中getRawSize方法只是根据设备将设置的数据转换单位返回。

其中measureLineHeight是在计算行高,measureCurrentScrollY是在计算纵向偏移量,这两个方法稍后就会介绍。

04

初始化尺寸及画笔

这些简单的初始化,就不再详细介绍了。

05

计算行高、行间距

之前行间距已经设置过了,当然,开发者不设置也是可以的,我已经设了默认值。

我们认为一行,应该包括一行文字和一个行间距,所以 行高=文字高度+行间距

计算文字高度,应该使用画笔的getTextBounds方法,从文字区域的Rect中获取文字所占的高度。

06

计算偏移量

既然LyricView能够实现滑动功能,那么引入scrollY值记录滑动偏移量,并控制视图绘制效果也就顺理成章。 需要明确一点,当偏移量scrollY的值为零的时候,歌词的首行将显示在整个LyricView的正中间 。

在上篇中,我们也知道每一句歌词中都包含着开始时间,而我们也就可以通过当前歌曲播放进度匹配当前播放的行数 mCurrentPlayLine,并通过当前播放所在行,计算偏移量scrollY的值,控制歌词播放滚动和当前播放位置的高亮显示。

这里还需注意,第一行的时候偏移量为0,所以计算对应偏移量的时候需要先减一

07

开始绘制

这样文字就可以绘制在屏幕上了,同时大家可能也看出来了,我设置了透明度,也就是淡入淡出效果。

注意:

  • 已经绘制过的不再进行绘制
  • 超出屏幕的不绘制
  • 不在中心区域的其他位置的字体设置透明度
  • 在中心区,也就是当前局无透明度

08

触摸事件、回弹效果

如果单纯实现视图滑动的功能的话,比较简单:只需要记录ACTION_DOWN时的y值,并比较ACTION_MOVE过程中的y值计算两者的差值,生成新的偏移量scrollY,再刷新视图,就可以了 !

但是,这样实现的话,用户一直滑动,整个歌词内容区域就会滑动出我们的可视区域,也就是常说的overScroll,如果不加以限制将会是一种非常差的用户体验。

与正常滑动时有所区别,滑动应该有一种阻尼效果:也就是实际滑动距离和视图的滚动距离并不相等,而且随着overScroll的值越大,阻力越大,滑动越艰难,并在用户手指离开屏幕后回到overScroll的值为零的位置。

其中VelocityTracker主要用跟踪触摸屏事件(flinging事件和其他gestures手势事件)的速率。

通过一次一次对代码的细化,只要这么简单的两个方法,就完成了滑动时偏移量scrollY的计算,包括overScroll和非overScroll。

到了这一步,歌词的显示、滑动查看都已经完成。

09

绘制指示器

到这里,歌词显示器就算完成了,有不对的地方还望大家指出。

原文发布于微信公众号 - Android机动车(JsAndroidClub)

原文发表时间:2017-11-06

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android知识点总结

Android关于Canvas你所知道的和不知道的一切

Picture相当于先拍一张照片,并且是在别的Canvas上,在别的Canvas上,在别的Canvas上! 重要的话说三遍:当需要的时候在贴在当前的canva...

53720
来自专栏分享达人秀

善用TableLayout表格布局,事半功倍

前面学习了线性布局和相对布局,线性布局虽然方便,但如果遇到控件需要排列整齐的情况就很难达到要求,用相对布局又比较麻烦,为此Android系统中提供了表格...

24490
来自专栏向治洪

VectorDrawable与AnimatedVectorDrawable

VectorDrawable  Android L开始提供了新的API VectorDrawable 可以使用SVG类型的资源,也就是矢量图。先来一个例子吧...

21650
来自专栏Micro_awake web

谈谈CSS中一些比较"偏门"的小知识 前面我写了:谈谈html中一些比较"偏门"的知识,现在这篇(主要)想谈谈个人所见的CSS一些小知识点,加深印象;同时也希望有需要的人能有收获!

前面我写了:谈谈html中一些比较"偏门"的知识,现在这篇(主要)想谈谈个人所见的CSS一些小知识点,加深印象;同时也希望有需要的人能有收获! 1.常见的浏览器...

20860
来自专栏腾讯NEXT学位

CSS布局解决方案(下)

25870
来自专栏编程

java基础知识,font属性css写法,代码详解!

CSS属性值 字体与文本 网页设计中有很多的文字要去处理,标题、段落、文章、列表以及表单中的文本。这一篇章我们讨论一下HTML中的字体与文本 字体 首先要有一...

20880
来自专栏cnblogs

Bootstrap源码分析之nav、collapse

导航分析(nav): 源码文件: _navs.scss:导航模块 Mixins/_nav-divider.scss:分隔线 Mixins/_nav-vertic...

33480
来自专栏HTML5学堂

CSS3圆角 border-radius

HTML5学堂:圆角是用一段与角的两边相切的圆弧替换原来的直角。在原有网页当中,如果需要实现圆角效果,可以使用背景图的实现,但是这样会造成背景图大小和数量的增加...

65170
来自专栏河湾欢儿的专栏

css3过渡与动画

过渡 当触发的时候会有过渡的效果 1.transition-property:none|all|某一个属性值 2.transition-duration:...

93410
来自专栏小轻论坛

一些实用的Photoshop快捷键

将所选文本的文字大小减小10 点像素 【Ctrl】+【Alt】+【Shift】+【<】

13430

扫码关注云+社区

领取腾讯云代金券