最近在以QQ音乐为样板做一个手机音乐播放器,源码下篇博文放出。今天我想聊的是这个QQ音乐播放器中歌词显示控件的问题,和小伙伴们一起来探讨怎么实现这个歌词滚动的效果。OK,废话不多说,先来看看效果图:

好,接下来我们就来看看怎么实现这样一个效果。本文主要包括如下几方面内容:

1.歌词文件格式分析及解析

2.歌词显示控件绘制

3.关于卡拉OK模式

4.使用方式

好,那就开始吧。

1.歌词文件格式分析及解析

首先,小伙伴们需要明白歌词文件的格式都是固定的,是什么样子的呢,我们来看看下图:

我们一个歌词文件打开都是这种格式,前面  []  中的是该行歌词显示的时间,后面一行是歌词,只有时间没有歌词的行就是伴奏时间。了解了这固定的歌词格式,剩下的就简单了,解析这段文本就行了。我创建一个LrcBean用来存放每一行的数据,这个LrcBean中包括三个属性,分别是一句歌词,该歌词开始唱的时间,该歌词唱完的时间,咦,有的小伙伴可能有疑问,唱完是什麽时候呢?就是下一句的开始时间呗。OK,那我们来看看实体类:

public class LrcBean {

private String lrc;

private long start;

private long end;

public LrcBean() {

}

public LrcBean(String text, long start, long end) {

this.lrc = text;

this.start = start;

this.end = end;

}

public String getLrc() {

return lrc;

}

public void setLrc(String lrc) {

this.lrc = lrc;

}

public long getStart() {

return start;

}

public void setStart(long start) {

this.start = start;

}

public long getEnd() {

return end;

}

public void setEnd(long end) {

this.end = end;

}

}

OK,实体类有了,接下来我们来看看实体类怎么解析歌词文本,解析过程分为两步:

1.考虑到歌词文本中可能有转义字符,我们需要先把转义字符还原

2.然后按照换行符将文本拆分,再通过字符串截取将每一行的数据提取出来。代码如下(由于转义字符显示不出来,所以我这里贴一张代码图,源码文末可以下载):

OK,通过以上方式我们就把歌词文件解析成了一个List集合,该集合中的每一项就是一句歌词,另外,在伴奏的时间段,我显示一句music。

2.歌词显示控件绘制

歌词解析完了,接下来我们就可以绘制歌词View了。绘制的整体思路是这样:

1.首先获取当前播放的时间

2.根据当前播放时间,遍历歌词的List集合,判断出当前正在播放的是List集合中的哪一句,找到该句的下标

3.遍历歌词List集合,绘制所有歌词,绘制的过程中,如果该句是正在播放的歌词,则使用高亮的画笔来绘制,否则使用普通画笔绘制。

4.判断当前是否已经换行了,如果是,则调用setScrollY方法让屏幕滚动一行。关于setScrollY方法如果小伙伴们还不太了解可以参考这篇文章View绘制详解(五),draw方法细节详解之View的滚动/滑动问题。

5.每隔100毫秒重绘View。

OK,整个流程就是这样,接下来我们来看看代码实现:

@Override

protected void onDraw(Canvas canvas) {

if (width == 0 || height == 0) {

width = getMeasuredWidth();

height = getMeasuredHeight();

}

if (list == null || list.size() == 0) {

canvas.drawText("暂无歌词", width / 2, height / 2, gPaint);

return;

}

getCurrentPosition();

int currentMillis = player.getCurrentPosition();

drawLrc2(canvas);

long start = list.get(currentPosition).getStart();

float v = (currentMillis - start) > 500 ? currentPosition * 80 : lastPosition * 80 + (currentPosition - lastPosition) * 80 * ((currentMillis - start) / 500f);

setScrollY((int) v);

if (getScrollY() == currentPosition * 80) {

lastPosition = currentPosition;

}

postInvalidateDelayed(100);

}

private void drawLrc2(Canvas canvas) {

for (int i = 0; i < list.size(); i++) {

if (i == currentPosition) {

canvas.drawText(list.get(i).getText(), width / 2, height / 2 + 80 * i, hPaint);

} else {

canvas.drawText(list.get(i).getText(), width / 2, height / 2 + 80 * i, gPaint);

}

}

}

private void getCurrentPosition() {

try {

int currentMillis = player.getCurrentPosition();

if (currentMillis < list.get(0).getStart()) {

currentPosition = 0;

return;

}

if (currentMillis > list.get(list.size() - 1).getStart()) {

currentPosition = list.size() - 1;

return;

}

for (int i = 0; i < list.size(); i++) {

if (currentMillis >= list.get(i).getStart() && currentMillis < list.get(i).getEnd()) {

currentPosition = i;

return;

}

}

} catch (Exception e) {

// e.printStackTrace();

postInvalidateDelayed(100);

}

}

OK,这里给出一个核心代码,完整代码小伙伴们在文末可以自行下载。

3.关于卡拉OK模式

OK,经过第二个步骤之后,我们这个歌词控件已经可以根据当前播放的时间来显示高亮的歌词,同时进行歌词的滚动。有的小伙伴可能还想实现一种类似于KTV里边的那种播放效果,我们也来看一看怎么实现。还是先来说说思路吧。

1.把所有的歌词都用普通的画笔画出来

2.为当前正在播放的歌词生成一个Bitmap

3.根据当前播放时间,计算出该句歌词播放的比例,然后根据这个比例绘制第二步生成的Bitmap。

OK,根据上述的思路,我贴出核心代码如下:

for (int i = 0; i < list.size(); i++) {

canvas.drawText(list.get(i).getLrc(), width / 2, height / 2 + 80 * i, gPaint);

}

String highLineLrc = list.get(currentPosition).getLrc();

int highLineWidth = (int) gPaint.measureText(highLineLrc);

int leftOffset = (width - highLineWidth) / 2;

LrcBean lrcBean = list.get(currentPosition);

long start = lrcBean.getStart();

long end = lrcBean.getEnd();

int i = (int) ((currentMillis - start) * 1.0f / (end - start) * highLineWidth);

if (i > 0) {

Bitmap textBitmap = Bitmap.createBitmap(i, 80, Bitmap.Config.ARGB_8888);

Canvas textCanvas = new Canvas(textBitmap);

textCanvas.drawText(highLineLrc, highLineWidth / 2, 80, hPaint);

canvas.drawBitmap(textBitmap, leftOffset, height / 2 + 80 * (currentPosition - 1), null);

}

4.使用方式

OK,控件做好了,最后我们再来看看使用方式。很简单,引入这个View 的类库(文末会给出下载地址),然后传入歌词的文本,开启绘制即可,如下:

lrcView.setLrc(lrcStr);

lrcView.setPlayer(PlayUtil.player);

lrcView.init();

简单三行代码,就可以开始使用了。

android仿qq音乐桌面歌词,Android自定义View,高仿QQ音乐歌词滚动控件!相关推荐

  1. Android自定义View精品(CustomCalendar-定制日历控件)

    版权声明:本文为openXu原创文章[openXu的博客],未经博主允许不得以任何形式转载 目录: 文章目录 1.分析 2.自定义属性 3.onMeasure() 4.onDraw() ①.绘制月份 ...

  2. 自定义View高仿懂球帝我是教练效果

    前言 这几天很多欧洲球队来中国进行热身赛,不知道喜欢足球的各位小伙伴们有没有看球.喜欢足球的朋友可能知道懂球帝APP,鄙人也经常使用这个应用,里面有一个我是教练的功能挺好玩,就是可以模拟教练员的身份, ...

  3. 自定义view高仿稀土掘金loading闪动字体效果

    注:该文章同步发布到稀土掘金:链接 前言 由于通勤时间较长,在路上总会有时间刷刷文章.稀土掘金就是常用的一个app(这里非广告,哈哈哈).前段时间,发表了篇文章:# 使用CollapsingToolb ...

  4. 自定义view之kotlin绘制精简小米时间控件

    引言 今天玩小米mix2的时候看到了小米的时间控件效果真的很棒.有各种动画效果,3d触摸效果,然后就想着自己能不能也实现一个这样的时间控件,那就开始行动绘制一个简易版本的小米时间控件吧o((≧▽≦o) ...

  5. 自定义view实战(11):滑动解锁九宫格控件

    前言 上一篇文章用贝塞尔曲线画了一个看起来不错的小红点功能,技术上没什么难度,主要就是数学上的计算.这篇文章也差不多,模仿了一个常用的滑动解锁的九宫格控件. 需求 用过安卓的都知道,用过苹果的也知道, ...

  6. 玩转自定义View之大学问特色蛛网评分控件

    在github上搜了一堆堆评分控件都没有理想中的样子所以在自己的开源项目上造了了轮子出来效果图如下: 先说明下理想中需求 支持任意大于等于3的评分 支持具有变色效果 支持分数以及图形分平均值描边 支持 ...

  7. Android 自定义view 高仿小米闹钟

    效果图: 代码github地址:https://github.com/chenzongwen/MiClockView

  8. 卡拉OK歌词原理和实现高仿Android网易云音乐

    大家好,我们是爱学啊,继上一篇讲解了[LRC歌词原理和实现高仿Android网易云音乐],今天给大家带来一篇关于卡拉OK歌词原理和在Android上如何实现歌词逐字滚动的效果,本文来自[Android ...

  9. Android自定义View之仿QQ运动步数进度效果

    文章目录 前言 先看效果图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6e4ddec17933496ea4830fa08d8ffbe5.png?x-oss-pr ...

  10. Android自定义View实战:简约风歌词控件

    作者:jsyjst 前言 最近重构了之前的音乐播放器,添加了许多功能,比如歌词,下载功能等.这篇文章就让我们聊聊歌词控件的实现,先上效果图,如果感觉海星,就继续瞧下去! 看到这里,估计你对这个控件还有 ...

最新文章

  1. 【分块】#6281. 数列分块入门 5(区间开方,区间求和)
  2. 公钥和私钥怎么生成_有趣图文帮你通俗易懂地理解公钥和私钥的区别以及与CA证书等概念...
  3. 手机存储sqlite还是mysql_手机存储 和sd 路径
  4. junit 验证日志输出_JUnit规则–引发异常时执行附加验证
  5. 长安渝北工厂机器人_长安UNI-T智能工厂:机器人、激光焊, 一分钟一台车
  6. AOSP6.0.1 launcher3入门篇—解析launcher.java文件
  7. mac 10.12.6 Fiddler的安装
  8. Python中各种括号的区别、用途及使用方法
  9. 在线的Sql格式化工具
  10. C0型单元刚度矩阵的性质
  11. 多质点列车动力学模型
  12. 微型计算机经历了那几个阶段,微型计算机的发展经历了哪几个阶段,各阶段微处理器的主要特征是什么...
  13. 2010~2011手机CPU对比
  14. 单目3D多人姿态估计网络(整合自上而下和自下而上网络)
  15. 苹果研发microLED暂难摆脱对三星的依赖
  16. Python模块查找路径
  17. android h5游戏图片不缓存,H5小游戏资源缓存方法与流程
  18. 阿里云服务器 之 mqtt服务器搭建及使用
  19. 02.国际标准文件查询
  20. 安卓软件开发基础教学!写给1-3年安卓程序员的几点建议,跳槽薪资翻倍

热门文章

  1. 隔离升压电源模块24V功率可达40W宽电压输入高电压稳压输出
  2. SpringBoot 请求相关
  3. 【Excel-2010】人口金字塔图
  4. 亚马逊的人工智能Alexa竟然独自大笑 笑声很吓人(附视频)
  5. 1004-史丰收速算
  6. Java 微信小程序笔记 三、 微信小程序邀请码生成
  7. win服务器系统安全模式,安全模式详解
  8. PC设置切换Fn功能键
  9. 计算机 玩体感游戏,Wii模拟器Dolphin完全教学 PC上也来玩体感
  10. 电子工程师是怎样的成长之路?