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

2018-08-03 14:42:43 浏览数 (1)

先看下效果

在上篇文章中呢,分享了关于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

绘制指示器

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

ntp

0 人点赞