Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能[转]

版权声明:本文为【欧阳鹏】原创文章,欢迎转载,转载请注明出处! 【http://blog.csdn.net/ouyang_peng/article/details/50813419

作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!  
转载请保留原文地址: 
http://blog.csdn.net/ouyang_peng/article/details/50813419

这里写图片描述

前言

最近有个项目有关于播放音乐时候,关于歌词有以下几个功能: 
1、实现歌词同步滚动的功能,即歌曲播放到哪句歌词,就高亮地显示出正在播放的这个歌词; 
2、实现上下拖动歌词时候,可以拖动播放器的进度。即可以不停地上下拖动歌词,当手指离开屏幕时候 即从当前拖动到的歌词位置播放。 
3、实现歌词的字体大小可以进行缩放的功能。即双指在屏幕进行缩放操作时,歌词的字体大小也进行相应的缩放操作。

下面我将这几个功能做成一个demo来展示给大家。首先来看看这个demo的具体实现效果,如下面几幅图所示。

图1、同步滚动歌词 
同步滚动歌词

图2、上下拖动歌词1 
上下拖动歌词1

图3、上下拖动歌词2 
上下拖动歌词2

图4、缩放歌词 
缩放歌词

图5、歌词显示(较大字体) 
歌词显示(较大字体)

图6、歌词显示(较小字体) 
歌词显示(较小字体)

图7、歌词滚动时候,高亮地画出正滚动到的歌词内容以及歌词的开始时间,并该句歌词下面画出一条直线 
歌词滚动截图


一、LRC歌词文件简介

1、什么是LRC歌词文件

lrc是英文lyric(歌词)的缩写,被用做歌词文件的扩展名。以lrc为扩展名的歌词文件可以在各类数码播放器中同步显示。

2、LRC歌词文件的格式

先来看一份标准的LRC歌词文件,下面展示的是王力宏的《依然爱你》的lrc歌词的内容

[ti:依然爱你]
[ar:王力宏]
[al:火力全开 新歌+精选]
[by:欧阳鹏]
[00:01.17]一闪一闪亮晶晶 留下岁月的痕迹 
[00:07.29]我的世界的重心 依然还是你
[00:13.37]一年一年又一年 飞逝尽在一转眼
[00:20.29]唯一永远不改变 是不停的改变
[00:27.14]我不像从前的自己 你也有点不像你
[00:33.36]但在我眼中你的笑 依然的美丽
[00:39.53]这次只能往前走 一个方向顺时钟
[00:46.12]不知道还要多久 所以要让你懂
[00:51.82]我依然爱你 就是唯一的退路
[00:57.36]我依然珍惜 时时刻刻的幸福
[01:04.65]你每个呼吸 每个动作 每个表情
[01:11.43]到最后一定会依然爱你
[01:18.08]依然爱你 依然爱你
[01:25.58]我不像从前的自己 你也有点不像你
[01:31.52]但在我眼中你的笑 依然的美丽
[01:37.61]这次只能往前走 一个方向顺时钟
[01:44.42]不知道还要多久 所以要让你懂
[01:50.18]我依然爱你 就是唯一的退路
[01:55.65]我依然珍惜 时时刻刻的幸福
[02:02.84]你每个呼吸 每个动作 每个表情
[02:09.77]到最后一定会依然爱你
[02:15.61]
[02:17.61]lrc制作:http://blog.csdn.net/ouyang_peng 欧阳鹏
[02:25.61]
[02:31.06]依然爱你 依然爱你
[02:36.63]
[02:42.32]我依然爱你 或许是命中注定
[02:47.70]多年之后 任何人都无法代替
[02:54.57]那些时光 是我这一辈子 最美好
[03:01.84]那些回忆 依然无法忘记 
[03:07.88]我依然爱你 就是唯一的退路
[03:13.95]我依然珍惜 时时刻刻的幸福
[03:21.32]你每个呼吸 每个动作 每个表情
[03:28.20]到最后一定会依然爱你
[03:34.76]你每个呼吸 每个动作 每个表情
[03:42.04]到永远一定会依然爱你
[03:53.28]
[04:01.28]  

LRC歌词文件的标签类型

lrc歌词文本中含有两类标签:一是标识标签 ,二是时间标签

1、标识标签

标识标签,其格式为“[标识名:值]”,主要包含以下预定义的标签:

  • [ar:歌手名]
  • [ti:歌曲名]
  • [al:专辑名]
  • [by:编辑者(指lrc歌词的制作人)]
  • [offset:时间补偿值] (其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的,但多数的MP3可能不会支持这种标签)。
2、时间标签

时间标签,形式为“[mm:ss]”或“[mm:ss.ff]”(分钟数:秒数.毫秒数),数字须为非负整数,

比如”[12:34.50]”是有效的,而”[0x0C:-34.50]”无效。

时间标签需位于某行歌词中的句首部分,一行歌词可以包含多个时间标签

(比如歌词中的迭句部分)。当歌曲播放到达某一时间点时,MP3就会寻找对应的时间标签并显示标签后面的歌词文本,这样就完成了“歌词同步”的功能。

例如下面的这首 草蜢的《失恋战线联盟》,就是一行歌词包含了多个时间标签。

[ti:失恋战线联盟]
[ar:草蜢]
[al:]
[00:00.00]草蜢-失恋战线联盟
[00:08.78]编辑:小婧
[01:43.33][00:16.27]她总是只留下电话号码
[01:46.97][00:19.81]从不肯让我送她回家
[01:50.61][00:23.43]听说你也曾经爱上过她
[01:54.15][00:27.07]曾经也同样无法自拔
[01:57.78][00:30.72]你说你学不会假装潇洒
[02:01.41][00:34.36]却叫我别太早放弃她
[02:05.05][00:37.99]把过去传说成一段神话
[02:08.70][00:41.59]然后笑你是一样的傻
[02:12.01][00:45.11]我们那么在乎她
[02:14.15][00:47.01]却被她全部抹杀
[02:15.96][00:48.87]越谈她越相信永远得不到回答
[02:19.57][00:52.49]到底她怎么想
[02:21.35][00:54.28]应该继续在这么
[02:23.37][00:56.36]还是说穿跑了吧
[02:26.89][00:59.80]找一个承认失恋的方法
[02:30.48][01:03.41]让心情好好地放个假
[02:34.14][01:07.00]当你我不小心又想起她
[02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
[02:48.69]
[01:33.58]编辑:小婧

[01:43.33][00:16.27]她总是只留下电话号码 
上面这行歌词表示:

在 [00:16.27] 这个时间点播放 “她总是只留下电话号码” 这句歌词,

在 [01:43.33] 这个时间点再一个播放 “她总是只留下电话号码” 这句歌词。

其实可以把上面这行歌词拆分为下面两句歌词:

[00:16.27]她总是只留下电话号码
[01:43.33]她总是只留下电话号码

二、解析LRC歌词

1、读取出歌词文件

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 从assets目录下读取歌词文件内容
         *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> fileName
         *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span>
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getFromAssets</span>(String fileName){
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                InputStreamReader inputReader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> InputStreamReader( getResources().getAssets().open(fileName) );
                BufferedReader bufReader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> BufferedReader(inputReader);
                String line=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
                String result=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>((line = bufReader.readLine()) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(line.trim().equals(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>))
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
                    result += line + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\r\n"</span>;
                }
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> result;
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
                e.printStackTrace();
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
        }
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

例如:从assets目录下读取test.lrc歌词文件内容,则可以调用上面的getFromAssets(String fileName)方法得到歌词的文本内容,如下所示:

<code class="hljs javascript has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> lrc = getFromAssets(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.lrc"</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

2、解析得到的歌词内容

1、表示每行歌词内容的实体类LrcRow

首先封装一个表示每行歌词内容的实体类LrcRow,该类由三个属性,分别为: 
strTime、time、content。

例如一行歌词内容为:[02:34.14]当你我不小心又想起她 , 解析该行歌词后的实体类LrcRow的属性如下所示:

  • strTime表示该行歌词要开始播放的时间,格式如下:[02:34.14]
  • time表示将strTime转换为long型之后的数值

    例如将strTime为[02:34.14]格式转换154014(154014=02 * 60 * 1000 + 34 * 1000+14)

  • content表示该行歌词的内容,如:当你我不小心又想起她

代码如下:

<code class="hljs scala has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view.impl;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.util.Log;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.ArrayList;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词行
     * 包括该行歌词的时间,歌词内容
     */</span>
    public <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LrcRow</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Comparable</span><<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LrcRow</span>>{</span>
        public <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> static String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LrcRow"</span>;

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 该行歌词要开始播放的时间,格式如下:[02:34.14] */</span>
        public String strTime;

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 该行歌词要开始播放的时间,由[02:34.14]格式转换为long型,
         * 即将2分34秒14毫秒都转为毫秒后 得到的long型值:time=02*60*1000+34*1000+14
         */</span>
        public long time;

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** 该行歌词的内容 */</span>
        public String content;


        public LrcRow(){}

        public LrcRow(String strTime,long time,String content){
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.strTime = strTime;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.time = time;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.content = content;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//      Log.d(TAG,"strTime:" + strTime + " time:" + time + " content:" + content);</span>
        }

        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        public String toString() {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"["</span> + strTime + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" ]"</span>  + content;
        }

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 读取歌词的每一行内容,转换为LrcRow,加入到集合中
         */</span>
        public static List<LrcRow> createRows(String standardLrcLine){
            <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
                一行歌词只有一个时间的  例如:徐佳莹   《我好想你》
                [01:15.33]我好想你 好想你

                一行歌词有多个时间的  例如:草蜢 《失恋战线联盟》
                [02:34.14][01:07.00]当你我不小心又想起她
                [02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
             **/</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>{
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(standardLrcLine.indexOf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"["</span>) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || standardLrcLine.indexOf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"]"</span>) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span> ){
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
                }
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//[02:34.14][01:07.00]当你我不小心又想起她</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//找到最后一个 ‘]’ 的位置</span>
                int lastIndexOfRightBracket = standardLrcLine.lastIndexOf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"]"</span>);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//歌词内容就是 ‘]’ 的位置之后的文本   eg:   当你我不小心又想起她</span>
                String content = standardLrcLine.substring(lastIndexOfRightBracket + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, standardLrcLine.length());
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//歌词时间就是 ‘]’ 的位置之前的文本   eg:   [02:34.14][01:07.00]</span>

                <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
                    将时间格式转换一下  [mm:ss.SS][mm:ss.SS] 转换为  -mm:ss.SS--mm:ss.SS-
                    即:[02:34.14][01:07.00]  转换为      -02:34.14--01:07.00-
                 */</span>
                String times = standardLrcLine.substring(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,lastIndexOfRightBracket + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>).replace(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"["</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"-"</span>).replace(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"]"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"-"</span>);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//通过 ‘-’ 来拆分字符串</span>
                String arrTimes[] = times.split(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"-"</span>);
                List<LrcRow> listTimes = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<LrcRow>();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(String temp : arrTimes){
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(temp.trim().length() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
                    }
                    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** [02:34.14][01:07.00]当你我不小心又想起她
                     *
                        上面的歌词的就可以拆分为下面两句歌词了
                        [02:34.14]当你我不小心又想起她
                        [01:07.00]当你我不小心又想起她
                     */</span>
                    LrcRow lrcRow = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LrcRow(temp, timeConvert(temp), content);
                    listTimes.add(lrcRow);
                }
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> listTimes;
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(Exception e){
                Log.e(TAG,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"createRows exception:"</span> + e.getMessage());
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            }
        }

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 将解析得到的表示时间的字符转化为Long型
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> static long timeConvert(String timeString){
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//因为给如的字符串的时间格式为XX:XX.XX,返回的long要求是以毫秒为单位</span>
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将字符串 XX:XX.XX 转换为 XX:XX:XX</span>
            timeString = timeString.replace(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'.'</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">':'</span>);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将字符串 XX:XX:XX 拆分</span>
            String[] times = timeString.split(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">":"</span>);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// mm:ss:SS</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> Integer.valueOf(times[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]) * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">60</span> * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span> +<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//分</span>
                    Integer.valueOf(times[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]) * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span> +<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//秒</span>
                    Integer.valueOf(times[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]) ;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//毫秒</span>
        }

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 排序的时候,根据歌词的时间来排序
         */</span>
        public int compareTo(LrcRow another) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (int)(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.time - another.time);
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li></ul>

该LrcRow的List createRows(String standardLrcLine)方法 ,将循环地一行一行的去读取歌词的内容。然后对每一行的歌词进行解析,每解析出一个时间标签[XX:XX.XX]则new出一个LrcRow对象,然后加入到歌词行List集合中去。

该LrcRow类实现Comparable接口,用来进行解析之后的排序操作,排序按时间从小到大排序。

2、解析歌词的构造器

ILrcBuilder接口

定义一个ILrcBuilder接口,接口有一个List getLrcRows(String rawLrc)方法,该方法用来解析歌词,得到LrcRow的集合

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.impl.LrcRow;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 解析歌词,得到LrcRow的集合
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ILrcBuilder</span> {</span>
        List<LrcRow> getLrcRows(String rawLrc);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>
DefaultLrcBuilder歌词解析构造器

DefaultLrcBuilder实现ILrcBuilder接口,List getLrcRows(String rawLrc)方法会循环地读取歌词的每一行,然后调用LrcRow类的List createRows(String standardLrcLine)方法,得到解析每一行歌词之后的LrcRow集合,再将每一行得到LrcRow集合中得到的LrcRow实体加入一个总 的到LrcRow集合rows中去,然后将rows集合根据歌词行的时间排序,得到排序后的LrcRow集合,该集合就是最终的解析歌词后的内容了。

代码如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view.impl;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.util.Log;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcBuilder;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.BufferedReader;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.IOException;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.StringReader;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.ArrayList;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.Collections;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 解析歌词,得到LrcRow的集合
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">DefaultLrcBuilder</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ILrcBuilder</span> {</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"DefaultLrcBuilder"</span>;

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> List<LrcRow> <span class="hljs-title" style="box-sizing: border-box;">getLrcRows</span>(String rawLrc) {
            Log.d(TAG,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getLrcRows by rawString"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(rawLrc == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || rawLrc.length() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                Log.e(TAG,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"getLrcRows rawLrc null or empty"</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            }
            StringReader reader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> StringReader(rawLrc);
            BufferedReader br = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> BufferedReader(reader);
            String line = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            List<LrcRow> rows = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<LrcRow>();
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>{
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//循环地读取歌词的每一行</span>
                do{
                    line = br.readLine();
                    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
                     一行歌词只有一个时间的  例如:徐佳莹   《我好想你》
                     [01:15.33]我好想你 好想你

                     一行歌词有多个时间的  例如:草蜢 《失恋战线联盟》
                     [02:34.14][01:07.00]当你我不小心又想起她
                     [02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
                     **/</span>
                    Log.d(TAG,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"lrc raw line: "</span> + line);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(line != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && line.length() > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析每一行歌词 得到每行歌词的集合,因为有些歌词重复有多个时间,就可以解析出多个歌词行来</span>
                        List<LrcRow> lrcRows = LrcRow.createRows(line);
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(lrcRows != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && lrcRows.size() > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(LrcRow row : lrcRows){
                                rows.add(row);
                            }
                        }
                    }
                }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(line != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>( rows.size() > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> ){
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 根据歌词行的时间排序</span>
                    Collections.sort(rows);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(rows!=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>&&rows.size()><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(LrcRow lrcRow:rows){
                            Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"lrcRow:"</span> + lrcRow.toString());
                        }
                    }
                }
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(Exception e){
                Log.e(TAG,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"parse exceptioned:"</span> + e.getMessage());
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
            }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">finally</span>{
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                    br.close();
                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IOException e) {
                    e.printStackTrace();
                }
                reader.close();
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> rows;
        }
    }
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li></ul>

例如:通过下面代码来调用ILrcBuilder解析歌词,

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//从assets目录下读取歌词文件内容</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">String</span> lrc <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> getFromAssets(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.lrc"</span>);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析歌词构造器</span>
        ILrcBuilder builder <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> <span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">new</span> DefaultLrcBuilder();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析歌词返回LrcRow集合</span>
        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">List</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>LrcRow<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">rows</span> <span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span> builder<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">.</span>getLrcRows(lrc);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
lrc歌词原始内容

草蜢的《失恋战线联盟》,lrc原始内容如下:

[ti:失恋战线联盟]
[ar:草蜢]
[al:]
[00:00.00]草蜢-失恋战线联盟
[00:08.78]编辑:小婧
[01:43.33][00:16.27]她总是只留下电话号码
[01:46.97][00:19.81]从不肯让我送她回家
[01:50.61][00:23.43]听说你也曾经爱上过她
[01:54.15][00:27.07]曾经也同样无法自拔
[01:57.78][00:30.72]你说你学不会假装潇洒
[02:01.41][00:34.36]却叫我别太早放弃她
[02:05.05][00:37.99]把过去传说成一段神话
[02:08.70][00:41.59]然后笑你是一样的傻
[02:12.01][00:45.11]我们那么在乎她
[02:14.15][00:47.01]却被她全部抹杀
[02:15.96][00:48.87]越谈她越相信永远得不到回答
[02:19.57][00:52.49]到底她怎么想
[02:21.35][00:54.28]应该继续在这么
[02:23.37][00:56.36]还是说穿跑了吧
[02:26.89][00:59.80]找一个承认失恋的方法
[02:30.48][01:03.41]让心情好好地放个假
[02:34.14][01:07.00]当你我不小心又想起她
[02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
[02:48.69]
[01:33.58]编辑:小婧

读取该歌词内容,过程中的打印日志为:

03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [ti:失恋战线联盟]
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [ar:草蜢]
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [al:]
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [00:00.00]草蜢-失恋战线联盟
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [00:08.78]编辑:小婧
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:43.33][00:16.27]她总是只留下电话号码
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:46.97][00:19.81]从不肯让我送她回家
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:50.61][00:23.43]听说你也曾经爱上过她
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:54.15][00:27.07]曾经也同样无法自拔
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:57.78][00:30.72]你说你学不会假装潇洒
03-06 00:41:15.352 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:01.41][00:34.36]却叫我别太早放弃她
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:05.05][00:37.99]把过去传说成一段神话
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:08.70][00:41.59]然后笑你是一样的傻
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:12.01][00:45.11]我们那么在乎她
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:14.15][00:47.01]却被她全部抹杀
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:15.96][00:48.87]越谈她越相信永远得不到回答
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:19.57][00:52.49]到底她怎么想
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:21.35][00:54.28]应该继续在这么
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:23.37][00:56.36]还是说穿跑了吧
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:26.89][00:59.80]找一个承认失恋的方法
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:30.48][01:03.41]让心情好好地放个假
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:34.14][01:07.00]当你我不小心又想起她
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:45.69][02:42.20][02:37.69][01:10.60]就在记忆里画一个叉
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [02:48.69]
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: [01:33.58]编辑:小婧
03-06 00:41:15.362 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrc raw line: null

解析歌词后遍历List集合的打印日志为:

03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:00.00 ]草蜢-失恋战线联盟
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:08.78 ]编辑:小婧
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:16.27 ]她总是只留下电话号码
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:19.81 ]从不肯让我送她回家
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:23.43 ]听说你也曾经爱上过她
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:27.07 ]曾经也同样无法自拔
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:30.72 ]你说你学不会假装潇洒
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:34.36 ]却叫我别太早放弃她
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:37.99 ]把过去传说成一段神话
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:41.59 ]然后笑你是一样的傻
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:45.11 ]我们那么在乎她
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:47.01 ]却被她全部抹杀
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:48.87 ]越谈她越相信永远得不到回答
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:52.49 ]到底她怎么想
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:54.28 ]应该继续在这么
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:56.36 ]还是说穿跑了吧
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[00:59.80 ]找一个承认失恋的方法
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:03.41 ]让心情好好地放个假
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:07.00 ]当你我不小心又想起她
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:10.60 ]就在记忆里画一个叉
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:33.58 ]编辑:小婧
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:43.33 ]她总是只留下电话号码
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:46.97 ]从不肯让我送她回家
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:50.61 ]听说你也曾经爱上过她
03-06 00:41:15.372 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:54.15 ]曾经也同样无法自拔
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[01:57.78 ]你说你学不会假装潇洒
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:01.41 ]却叫我别太早放弃她
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:05.05 ]把过去传说成一段神话
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:08.70 ]然后笑你是一样的傻
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:12.01 ]我们那么在乎她
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:14.15 ]却被她全部抹杀
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:15.96 ]越谈她越相信永远得不到回答
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:19.57 ]到底她怎么想
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:21.35 ]应该继续在这么
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:23.37 ]还是说穿跑了吧
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:26.89 ]找一个承认失恋的方法
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:30.48 ]让心情好好地放个假
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:34.14 ]当你我不小心又想起她
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:37.69 ]就在记忆里画一个叉
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:42.20 ]就在记忆里画一个叉
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:45.69 ]就在记忆里画一个叉
03-06 00:41:15.382 5265-5265/com.oyp.lrc D/DefaultLrcBuilder: lrcRow:[02:48.69 ]
lrc歌词解析后的内容

即,草蜢的《失恋战线联盟》的lrc歌词解析完后的内容如下:

[00:00.00 ]草蜢-失恋战线联盟
[00:08.78 ]编辑:小婧
[00:16.27 ]她总是只留下电话号码
[00:19.81 ]从不肯让我送她回家
[00:23.43 ]听说你也曾经爱上过她
[00:27.07 ]曾经也同样无法自拔
[00:30.72 ]你说你学不会假装潇洒
[00:34.36 ]却叫我别太早放弃她
[00:37.99 ]把过去传说成一段神话
[00:41.59 ]然后笑你是一样的傻
[00:45.11 ]我们那么在乎她
[00:47.01 ]却被她全部抹杀
[00:48.87 ]越谈她越相信永远得不到回答
[00:52.49 ]到底她怎么想
[00:54.28 ]应该继续在这么
[00:56.36 ]还是说穿跑了吧
[00:59.80 ]找一个承认失恋的方法
[01:03.41 ]让心情好好地放个假
[01:07.00 ]当你我不小心又想起她
[01:10.60 ]就在记忆里画一个叉
[01:33.58 ]编辑:小婧
[01:43.33 ]她总是只留下电话号码
[01:46.97 ]从不肯让我送她回家
[01:50.61 ]听说你也曾经爱上过她
[01:54.15 ]曾经也同样无法自拔
[01:57.78 ]你说你学不会假装潇洒
[02:01.41 ]却叫我别太早放弃她
[02:05.05 ]把过去传说成一段神话
[02:08.70 ]然后笑你是一样的傻
[02:12.01 ]我们那么在乎她
[02:14.15 ]却被她全部抹杀
[02:15.96 ]越谈她越相信永远得不到回答
[02:19.57 ]到底她怎么想
[02:21.35 ]应该继续在这么
[02:23.37 ]还是说穿跑了吧
[02:26.89 ]找一个承认失恋的方法
[02:30.48 ]让心情好好地放个假
[02:34.14 ]当你我不小心又想起她
[02:37.69 ]就在记忆里画一个叉
[02:42.20 ]就在记忆里画一个叉
[02:45.69 ]就在记忆里画一个叉
[02:48.69 ]

下面是解析歌词前后的对比图 
这里写图片描述

至此,歌词解析完毕!


三、显示LRC歌词内容

1、定义一个ILrcViewListener接口

ILrcViewListener接口,该接口定义了一个onLrcSeeked方法用来监听用户上下拖动歌词的动作定义了一个方法

  • onLrcSeeked(int newPosition, LrcRow row)

当歌词被用户上下拖动的时候回调该方法

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.impl.LrcRow;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词拖动时候的监听类
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ILrcViewListener</span> {</span>
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 当歌词被用户上下拖动的时候回调该方法
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> onLrcSeeked(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> newPosition, LrcRow row);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

2、定义一个ILrcView接口

ILrcView接口接口,定义了三个方法

  • setLrc(List lrcRows)

调用该方法设置要展示的歌词行集合

  • seekLrcToTime(long time)

    音乐播放的时候调用该方法滚动歌词,高亮正在播放的那句歌词

  • setListener(ILrcViewListener l)

    调用该方法设设置歌词拖动时候的监听类,用以回调ILrcViewListener的onLrcSeeked(int newPosition, LrcRow row)方法

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.impl.LrcRow;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 展示歌词的接口
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ILrcView</span> {</span>

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 设置要展示的歌词行集合
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> setLrc(List<LrcRow> lrcRows);

        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 音乐播放的时候调用该方法滚动歌词,高亮正在播放的那句歌词
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> seekLrcToTime(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> time);
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 设置歌词拖动时候的监听类
         */</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> setListener(ILrcViewListener l);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li></ul>

3、自定义一个LrcView

自定义一个LrcView,该LrcView继承android.view.View对象,实现了ILrcView接口。该自定义LrcView可以实现了同步显示歌词,拖动歌词,缩放歌词等功能。

同步显示歌词功能

首先来说说显示歌词的实现思路,要显示歌词即把歌词的内容绘制出来,可以分以下三步来绘制歌词:

第1步:高亮地画出正在播放的那句歌词

第2步:画出正在播放的那句歌词的上面可以展示出来的歌词

第3步:画出正在播放的那句歌词的下面的可以展示出来的歌词

重写onDraw(Canvas canvas)方法,在方法中按照上面的思路来绘制者三部分的歌词。代码如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onDraw</span>(Canvas canvas) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height = getHeight(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// height of this view</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width = getWidth(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// width of this view</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当没有歌词的时候</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoadingLrcTip != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// draw tip when no lrc.</span>
                mPaint.setColor(mHignlightRowColor);
                mPaint.setTextSize(mLrcFontSize);
                mPaint.setTextAlign(Align.CENTER);
                canvas.drawText(mLoadingLrcTip, width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mLrcFontSize, mPaint);
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowY = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// vertical point of each row.</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowX = width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowNum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 分以下三步来绘制歌词:
         *
         *  第1步:高亮地画出正在播放的那句歌词
         *  第2步:画出正在播放的那句歌词的上面可以展示出来的歌词
         *  第3步:画出正在播放的那句歌词的下面的可以展示出来的歌词
         */</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、 高亮地画出正在要高亮的的那句歌词</span>
        String highlightText = mLrcRows.get(mHignlightRow).content;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> highlightRowY = height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mLrcFontSize;
        mPaint.setColor(mHignlightRowColor);
        mPaint.setTextSize(mLrcFontSize);
        mPaint.setTextAlign(Align.CENTER);
        canvas.drawText(highlightText, rowX, highlightRowY, mPaint);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 上下拖动歌词的时候 画出拖动要高亮的那句歌词的时间 和 高亮的那句歌词下面的一条直线</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 画出高亮的那句歌词下面的一条直线</span>
            mPaint.setColor(mSeekLineColor);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//该直线的x坐标从0到屏幕宽度  y坐标为高亮歌词和下一行歌词中间</span>
            canvas.drawLine(mSeekLinePaddingX, highlightRowY + mPaddingY, width - mSeekLinePaddingX, highlightRowY + mPaddingY, mPaint);

            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 画出高亮的那句歌词的时间</span>
            mPaint.setColor(mSeekLineTextColor);
            mPaint.setTextSize(mSeekLineTextSize);
            mPaint.setTextAlign(Align.LEFT);
            canvas.drawText(mLrcRows.get(mHignlightRow).strTime, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, highlightRowY, mPaint);
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、画出正在播放的那句歌词的上面可以展示出来的歌词</span>
        mPaint.setColor(mNormalRowColor);
        mPaint.setTextSize(mLrcFontSize);
        mPaint.setTextAlign(Align.CENTER);
        rowNum = mHignlightRow - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        rowY = highlightRowY - mPaddingY - mLrcFontSize;
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只画出正在播放的那句歌词的上一句歌词</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        if (rowY > -mLrcFontSize && rowNum >= 0) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            String text = mLrcRows.get(rowNum).content;</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            canvas.drawText(text, rowX, rowY, mPaint);</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        }</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画出正在播放的那句歌词的上面所有的歌词</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>( rowY > -mLrcFontSize && rowNum >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
            String text = mLrcRows.get(rowNum).content;
            canvas.drawText(text, rowX, rowY, mPaint);
            rowY -=  (mPaddingY + mLrcFontSize);
            rowNum --;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、画出正在播放的那句歌词的下面的可以展示出来的歌词</span>
        rowNum = mHignlightRow + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        rowY = highlightRowY + mPaddingY + mLrcFontSize;

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只画出正在播放的那句歌词的下一句歌词</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        if (rowY < height && rowNum < mLrcRows.size()) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            String text2 = mLrcRows.get(rowNum).content;</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            canvas.drawText(text2, rowX, rowY, mPaint);</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        }</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画出正在播放的那句歌词的所有下面的可以展示出来的歌词</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>( rowY < height && rowNum < mLrcRows.size()){
            String text = mLrcRows.get(rowNum).content;
            canvas.drawText(text, rowX, rowY, mPaint);
            rowY += (mPaddingY + mLrcFontSize);
            rowNum ++;
        }

    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li></ul>

为了实现同步显示功能的功能,则需要不停地将自定义的LrcView进行重绘。首先当MediaPlayer开始播放的时候,同步的启动一个TimerTask来进行歌词的滚动操作。如代码所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">mPlayer.setOnPreparedListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnPreparedListener() {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//准备完毕</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPrepared</span>(MediaPlayer mp) {
                    mp.start();
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mTimer == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
                        mTimer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Timer();
                        mTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LrcTask();
                        mTimer.scheduleAtFixedRate(mTask, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, mPalyTimerDuration);
                    }
                }
            });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

上面代码的意思是,当MediaPlayer开始播放的时候,启动一个定时器Timer,然后通过这个定时器每隔mPalyTimerDuration时间来执行一次LrcTask任务。LrcTask的代码如下:

<code class="hljs scala has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 展示歌曲的定时任务
     */</span>
    <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LrcTask</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">TimerTask</span>{</span>
        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        public void run() {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取歌曲播放的位置</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> long timePassed = mPlayer.getCurrentPosition();
            MainActivity.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.runOnUiThread(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Runnable() {
                public void run() {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//滚动歌词</span>
                    mLrcView.seekLrcToTime(timePassed);
                }
            });

        }
    };</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>

上面的代码是:首先获取MediaPlayer的播放进度值,然后调用了LrcView的seekLrcToTime(long time)方法进行歌词同步滚动,LrcView的seekLrcToTime(long time)方法的实现代码如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 播放的时候调用该方法滚动歌词,高亮正在播放的那句歌词
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> time
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">seekLrcToTime</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> time) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode != DISPLAY_MODE_NORMAL) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"seekLrcToTime:"</span> + time);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < mLrcRows.size(); i++) {
            LrcRow current = mLrcRows.get(i);
            LrcRow next = i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> == mLrcRows.size() ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> : mLrcRows.get(i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
             *  正在播放的时间大于current行的歌词的时间而小于next行歌词的时间, 设置要高亮的行为current行
             *  正在播放的时间大于current行的歌词,而current行为最后一句歌词时,设置要高亮的行为current行
             */</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((time >= current.time && next != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && time < next.time)
                    || (time > current.time && next == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)){
                seekLrc(i, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
            }
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li></ul>

上面代码意思是,首先通过传入进来的MediaPlayer的播放进度值,来判断需要高亮地歌词行LrcRow是哪一行,然后调用seekLrc(int position, boolean cb)方法来进行歌词重绘操作。seekLrc(int position, boolean cb)方法的实现如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置要高亮的歌词为第几行歌词
     *
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> position 要高亮的歌词行数
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> cb       是否是手指拖动后要高亮的歌词
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">seekLrc</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> cb) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || position < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || position > mLrcRows.size()) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        LrcRow lrcRow = mLrcRows.get(position);
        mHignlightRow = position;
        invalidate();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是手指拖动歌词后</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcViewListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && cb) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调onLrcSeeked方法,将音乐播放器播放的位置移动到高亮歌词的位置</span>
            mLrcViewListener.onLrcSeeked(position, lrcRow);
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

上面方法是将要高亮的歌词行设置为目前正在播放的歌词行,然后重绘LrcView。

拖动歌词的功能

要实现拖动歌词的功能,可以分为以下几步来实现 
1、给LrcView注册一个ILrcViewListener监听接口。

下面是LrcView注册ILrcViewListener监听的具体实现。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置自定义的LrcView上下拖动歌词时监听</span>
        mLrcView.setListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ILrcViewListener() {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当歌词被用户上下拖动的时候回调该方法,从高亮的那一句歌词开始播放</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLrcSeeked</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> newPosition, LrcRow row) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPlayer != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                    Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"onLrcSeeked:"</span> + row.time);
                    mPlayer.seekTo((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) row.time);
                }
            }
        });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

2、当歌词进行拖动的时候,回调ILrcViewListener接口的onLrcSeeked(int newPosition, LrcRow row)方法。

如下面代码所示:回调了onLrcSeeked(int newPosition, LrcRow row)方法。

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置要高亮的歌词为第几行歌词
     *
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> position 要高亮的歌词行数
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> cb       是否是手指拖动后要高亮的歌词
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">seekLrc</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> cb) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || position < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || position > mLrcRows.size()) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        LrcRow lrcRow = mLrcRows.get(position);
        mHignlightRow = position;
        invalidate();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是手指拖动歌词后</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcViewListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && cb) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调onLrcSeeked方法,将音乐播放器播放的位置移动到高亮歌词的位置</span>
            mLrcViewListener.onLrcSeeked(position, lrcRow);
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li></ul>

3、判断手指在屏幕上的操作,来进行歌词滚动的操作。 
重写onTouchEvent(MotionEvent event)方法,来判断手指的操作是拖动歌词还是缩放歌词。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> @Override
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> boolean <span class="hljs-title" style="box-sizing: border-box;">onTouchEvent</span>(MotionEvent <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> super.onTouchEvent(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getAction()) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指按下</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_DOWN:
                Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"down,mLastMotionY:"</span> + mLastMotionY);
                mLastMotionY = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getY();
                mIsFirstMove = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                invalidate();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指移动</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_MOVE:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getPointerCount() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) {
                    Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"two move"</span>);
                    doScale(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"one move"</span>);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// single pointer mode ,seek</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是双指同时按下,进行歌词大小缩放,抬起其中一个手指,另外一个手指不离开屏幕地移动的话,不做任何处理</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SCALE) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//if scaling but pointer become not two ,do nothing.</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果一个手指按下,在屏幕上移动的话,拖动歌词上下</span>
                doSeek(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_CANCEL:
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指抬起</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_UP:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//高亮手指抬起时的歌词并播放从该句歌词开始播放</span>
                    seekLrc(mHignlightRow, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
                }
                mDisplayMode = DISPLAY_MODE_NORMAL;
                invalidate();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li></ul>

如上代码所示,当一个手指移动的时候,则调用doSeek(MotionEvent event)方法来进行拖动歌词的操作,doSeek(MotionEvent event)方法的具体实现代码如下:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 处理单指在屏幕移动时,歌词上下滚动
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">doSeek</span>(MotionEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y = event.getY();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指当前位置的y坐标</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> offsetY = y - mLastMotionY; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次按下的y坐标和目前移动手指位置的y坐标之差</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果移动距离小于10,不做任何处理</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (Math.abs(offsetY) < mMinSeekFiredOffset) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将模式设置为拖动歌词模式</span>
        mDisplayMode = DISPLAY_MODE_SEEK;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowOffset = Math.abs((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) offsetY / mLrcFontSize); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//歌词要滚动的行数</span>

        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"move to new hightlightrow : "</span> + mHignlightRow + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" offsetY: "</span> + offsetY + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" rowOffset:"</span> + rowOffset);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (offsetY < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指向上移动,歌词向下滚动</span>
            mHignlightRow += rowOffset;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为 当前高亮歌词 向下滚动rowOffset行后的歌词</span>
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (offsetY > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指向下移动,歌词向上滚动</span>
            mHignlightRow -= rowOffset;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为 当前高亮歌词 向上滚动rowOffset行后的歌词</span>
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为0和mHignlightRow中的较大值,即如果mHignlightRow < 0,mHignlightRow=0</span>
        mHignlightRow = Math.max(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, mHignlightRow);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为0和mHignlightRow中的较小值,即如果mHignlight > RowmLrcRows.size()-1,mHignlightRow=mLrcRows.size()-1</span>
        mHignlightRow = Math.min(mHignlightRow, mLrcRows.size() - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果歌词要滚动的行数大于0,则重画LrcView</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (rowOffset > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            mLastMotionY = y;
            invalidate();
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>

如上面代码所示,当一个手指不停的在屏幕上移动时,将会不停地调用doSeek(MotionEvent event)方法来进行LrcView的重绘操作,从而实现了歌词拖动的效果。

当手指离开屏幕的时候,即MotionEvent 为MotionEvent.ACTION_UP的时候,会调用seekLrc(int position, boolean cb)方法,从而回调ILrcViewListener接口的onLrcSeeked方法,来拖动MediaPlayer的播放进度值,从而达到了拖动歌词后从最终高亮的歌词开始重新播放歌词的功能。如下代码所示:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_UP:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//高亮手指抬起时的歌词并播放从该句歌词开始播放</span>
                    seekLrc(mHignlightRow, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
                }
                mDisplayMode = DISPLAY_MODE_NORMAL;
                invalidate();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

缩放歌词的功能

如onTouchEvent(MotionEvent event)方法中所示,当两个手指在屏幕上移动的时候,调用doScale(MotionEvent event)方法来做缩放歌词的功能。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_MOVE:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>.getPointerCount() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) {
                    Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"two move"</span>);
                    doScale(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"one move"</span>);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// single pointer mode ,seek</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是双指同时按下,进行歌词大小缩放,抬起其中一个手指,另外一个手指不离开屏幕地移动的话,不做任何处理</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SCALE) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//if scaling but pointer become not two ,do nothing.</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果一个手指按下,在屏幕上移动的话,拖动歌词上下</span>
                doSeek(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">event</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

doScale(MotionEvent event)方法的具体实现代码如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 处理双指在屏幕移动时的,歌词大小缩放
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">doScale</span>(MotionEvent event) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果歌词的模式为:拖动歌词模式</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是单指按下,在进行歌词上下滚动,然后按下另外一个手指,则把歌词模式从 拖动歌词模式 变为 缩放歌词模式</span>
            mDisplayMode = DISPLAY_MODE_SCALE;
            Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"change mode from DISPLAY_MODE_SEEK to DISPLAY_MODE_SCALE"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// two pointer mode , scale font</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mIsFirstMove) {
            mDisplayMode = DISPLAY_MODE_SCALE;
            invalidate();
            mIsFirstMove = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//两个手指的x坐标和y坐标</span>
            setTwoPointerLocation(event);
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取歌词大小要缩放的比例</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> scaleSize = getScale(event);
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize:"</span> + scaleSize);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果缩放大小不等于0,进行缩放,重绘LrcView</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (scaleSize != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            setNewFontSize(scaleSize);
            invalidate();
        }
        setTwoPointerLocation(event);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li></ul>

如上代码所示,当两个手指第一次放在屏幕上时候,调用setTwoPointerLocation(MotionEvent event)方法来记录两个手指的x坐标和y坐标,setTwoPointerLocation(MotionEvent event)方法代码如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"> <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置当前两个手指的x坐标和y坐标
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setTwoPointerLocation</span>(MotionEvent event) {
        mPointerOneLastMotion.x = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        mPointerOneLastMotion.y = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        mPointerTwoLastMotion.x = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        mPointerTwoLastMotion.y = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

当两个手指在屏幕上移动的时候,调用getScale(MotionEvent event)方法来对比两个手指前后两次的x坐标和y坐标,从而得到要缩放的比例scaleSize。getScale(MotionEvent event)方法具体实现如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 获取歌词大小要缩放的比例
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getScale</span>(MotionEvent event) {
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize getScale"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x0 = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y0 = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x1 = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y1 = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> maxOffset = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// max offset between x or y axis,used to decide scale size</span>

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> zoomin = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次双指之间的x坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> oldXOffset = Math.abs(mPointerOneLastMotion.x - mPointerTwoLastMotion.x);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第二次双指之间的x坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> newXoffset = Math.abs(x1 - x0);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次双指之间的y坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> oldYOffset = Math.abs(mPointerOneLastMotion.y - mPointerTwoLastMotion.y);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第二次双指之间的y坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> newYoffset = Math.abs(y1 - y0);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//双指移动之后,判断双指之间移动的最大差距</span>
        maxOffset = Math.max(Math.abs(newXoffset - oldXOffset), Math.abs(newYoffset - oldYOffset));
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果x坐标移动的多一些</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (maxOffset == Math.abs(newXoffset - oldXOffset)) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果第二次双指之间的x坐标的差距大于第一次双指之间的x坐标的差距则是放大,反之则缩小</span>
            zoomin = newXoffset > oldXOffset ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果y坐标移动的多一些</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果第二次双指之间的y坐标的差距大于第一次双指之间的y坐标的差距则是放大,反之则缩小</span>
            zoomin = newYoffset > oldYOffset ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        }
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize maxOffset:"</span> + maxOffset);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (zoomin) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (maxOffset / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//放大双指之间移动的最大差距的1/10</span>
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (maxOffset / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//缩小双指之间移动的最大差距的1/10</span>
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li></ul>

当通过getScale(MotionEvent event)方法获得了缩放比scaleSize后,调用setNewFontSize(int scaleSize)来设置歌词的新的字体大小,然后重绘LrcView,从而实现了缩放歌词的功能。 
setNewFontSize(int scaleSize)方法的具体实现如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">   <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置缩放后的字体大小
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setNewFontSize</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> scaleSize) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置歌词缩放后的的最新字体大小</span>
        mLrcFontSize += scaleSize;
        mLrcFontSize = Math.max(mLrcFontSize, mMinLrcFontSize);
        mLrcFontSize = Math.min(mLrcFontSize, mMaxLrcFontSize);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置显示高亮的那句歌词的时间最新字体大小</span>
        mSeekLineTextSize += scaleSize;
        mSeekLineTextSize = Math.max(mSeekLineTextSize, mMinSeekLineTextSize);
        mSeekLineTextSize = Math.min(mSeekLineTextSize, mMaxSeekLineTextSize);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>

至此,缩放功能已经实现。


LrcView的全部代码如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc.view.impl;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.content.Context;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.graphics.Canvas;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.graphics.Color;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.graphics.Paint;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.graphics.Paint.Align;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.graphics.PointF;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.util.AttributeSet;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.util.Log;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.view.MotionEvent;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.view.View;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcView;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcViewListener;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;

<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
 * 自定义LrcView,可以同步显示歌词,拖动歌词,缩放歌词
 */</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">LrcView</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">View</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ILrcView</span> {</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LrcView"</span>;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 正常歌词模式
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> DISPLAY_MODE_NORMAL = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词模式
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> DISPLAY_MODE_SEEK = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 缩放歌词模式
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> DISPLAY_MODE_SCALE = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词的当前展示模式
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mDisplayMode = DISPLAY_MODE_NORMAL;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词集合,包含所有行的歌词
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> List<LrcRow> mLrcRows;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 最小移动的距离,当拖动歌词时如果小于该距离不做处理
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMinSeekFiredOffset = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 当前高亮歌词的行数
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mHignlightRow = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 当前高亮歌词的字体颜色为黄色
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mHignlightRowColor = Color.YELLOW;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 不高亮歌词的字体颜色为白色
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mNormalRowColor = Color.WHITE;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,在当前高亮歌词下面的一条直线的字体颜色
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSeekLineColor = Color.CYAN;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,展示当前高亮歌词的时间的字体颜色
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSeekLineTextColor = Color.CYAN;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,展示当前高亮歌词的时间的字体大小默认值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSeekLineTextSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,展示当前高亮歌词的时间的字体大小最小值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMinSeekLineTextSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">13</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,展示当前高亮歌词的时间的字体大小最大值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMaxSeekLineTextSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词字体大小默认值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mLrcFontSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">23</span>;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// font size of lrc</span>
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词字体大小最小值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMinLrcFontSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">15</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 歌词字体大小最大值
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mMaxLrcFontSize = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">35</span>;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 两行歌词之间的间距
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mPaddingY = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词时,在当前高亮歌词下面的一条直线的起始位置
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mSeekLinePaddingX = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 拖动歌词的监听类,回调LrcViewListener类的onLrcSeeked方法
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ILrcViewListener mLrcViewListener;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 当没有歌词的时候展示的内容
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String mLoadingLrcTip = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Downloading lrc..."</span>;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Paint mPaint;

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">LrcView</span>(Context context, AttributeSet attr) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context, attr);
        mPaint = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(mLrcFontSize);
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setListener</span>(ILrcViewListener l) {
        mLrcViewListener = l;
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setLoadingTipText</span>(String text) {
        mLoadingLrcTip = text;
    }

    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onDraw</span>(Canvas canvas) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> height = getHeight(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// height of this view</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> width = getWidth(); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// width of this view</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当没有歌词的时候</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLoadingLrcTip != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// draw tip when no lrc.</span>
                mPaint.setColor(mHignlightRowColor);
                mPaint.setTextSize(mLrcFontSize);
                mPaint.setTextAlign(Align.CENTER);
                canvas.drawText(mLoadingLrcTip, width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mLrcFontSize, mPaint);
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowY = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// vertical point of each row.</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowX = width / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowNum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;
        <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
         * 分以下三步来绘制歌词:
         *
         *  第1步:高亮地画出正在播放的那句歌词
         *  第2步:画出正在播放的那句歌词的上面可以展示出来的歌词
         *  第3步:画出正在播放的那句歌词的下面的可以展示出来的歌词
         */</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1、 高亮地画出正在要高亮的的那句歌词</span>
        String highlightText = mLrcRows.get(mHignlightRow).content;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> highlightRowY = height / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> - mLrcFontSize;
        mPaint.setColor(mHignlightRowColor);
        mPaint.setTextSize(mLrcFontSize);
        mPaint.setTextAlign(Align.CENTER);
        canvas.drawText(highlightText, rowX, highlightRowY, mPaint);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 上下拖动歌词的时候 画出拖动要高亮的那句歌词的时间 和 高亮的那句歌词下面的一条直线</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 画出高亮的那句歌词下面的一条直线</span>
            mPaint.setColor(mSeekLineColor);
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//该直线的x坐标从0到屏幕宽度  y坐标为高亮歌词和下一行歌词中间</span>
            canvas.drawLine(mSeekLinePaddingX, highlightRowY + mPaddingY, width - mSeekLinePaddingX, highlightRowY + mPaddingY, mPaint);

            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 画出高亮的那句歌词的时间</span>
            mPaint.setColor(mSeekLineTextColor);
            mPaint.setTextSize(mSeekLineTextSize);
            mPaint.setTextAlign(Align.LEFT);
            canvas.drawText(mLrcRows.get(mHignlightRow).strTime, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, highlightRowY, mPaint);
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 2、画出正在播放的那句歌词的上面可以展示出来的歌词</span>
        mPaint.setColor(mNormalRowColor);
        mPaint.setTextSize(mLrcFontSize);
        mPaint.setTextAlign(Align.CENTER);
        rowNum = mHignlightRow - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        rowY = highlightRowY - mPaddingY - mLrcFontSize;
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只画出正在播放的那句歌词的上一句歌词</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        if (rowY > -mLrcFontSize && rowNum >= 0) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            String text = mLrcRows.get(rowNum).content;</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            canvas.drawText(text, rowX, rowY, mPaint);</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        }</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画出正在播放的那句歌词的上面所有的歌词</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>( rowY > -mLrcFontSize && rowNum >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){
            String text = mLrcRows.get(rowNum).content;
            canvas.drawText(text, rowX, rowY, mPaint);
            rowY -=  (mPaddingY + mLrcFontSize);
            rowNum --;
        }

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 3、画出正在播放的那句歌词的下面的可以展示出来的歌词</span>
        rowNum = mHignlightRow + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
        rowY = highlightRowY + mPaddingY + mLrcFontSize;

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//只画出正在播放的那句歌词的下一句歌词</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        if (rowY < height && rowNum < mLrcRows.size()) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            String text2 = mLrcRows.get(rowNum).content;</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//            canvas.drawText(text2, rowX, rowY, mPaint);</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//        }</span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//画出正在播放的那句歌词的所有下面的可以展示出来的歌词</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>( rowY < height && rowNum < mLrcRows.size()){
            String text = mLrcRows.get(rowNum).content;
            canvas.drawText(text, rowX, rowY, mPaint);
            rowY += (mPaddingY + mLrcFontSize);
            rowNum ++;
        }

    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置要高亮的歌词为第几行歌词
     *
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> position 要高亮的歌词行数
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> cb       是否是手指拖动后要高亮的歌词
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">seekLrc</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> position, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> cb) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || position < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || position > mLrcRows.size()) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        LrcRow lrcRow = mLrcRows.get(position);
        mHignlightRow = position;
        invalidate();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是手指拖动歌词后</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcViewListener != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && cb) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//回调onLrcSeeked方法,将音乐播放器播放的位置移动到高亮歌词的位置</span>
            mLrcViewListener.onLrcSeeked(position, lrcRow);
        }
    }

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> mLastMotionY;
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 第一个手指的坐标
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> PointF mPointerOneLastMotion = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PointF();
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 第二个手指的坐标
     **/</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> PointF mPointerTwoLastMotion = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PointF();
    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 是否是第一次移动,当一个手指按下后开始移动的时候,设置为true,
     * 当第二个手指按下的时候,即两个手指同时移动的时候,设置为false
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> mIsFirstMove = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;

    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onTouchEvent</span>(MotionEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onTouchEvent(event);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">switch</span> (event.getAction()) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指按下</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_DOWN:
                Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"down,mLastMotionY:"</span> + mLastMotionY);
                mLastMotionY = event.getY();
                mIsFirstMove = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                invalidate();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指移动</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_MOVE:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (event.getPointerCount() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) {
                    Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"two move"</span>);
                    doScale(event);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"one move"</span>);
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// single pointer mode ,seek</span>
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是双指同时按下,进行歌词大小缩放,抬起其中一个手指,另外一个手指不离开屏幕地移动的话,不做任何处理</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SCALE) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//if scaling but pointer become not two ,do nothing.</span>
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
                }
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果一个手指按下,在屏幕上移动的话,拖动歌词上下</span>
                doSeek(event);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_CANCEL:
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指抬起</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">case</span> MotionEvent.ACTION_UP:
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//高亮手指抬起时的歌词并播放从该句歌词开始播放</span>
                    seekLrc(mHignlightRow, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);
                }
                mDisplayMode = DISPLAY_MODE_NORMAL;
                invalidate();
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>;
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 处理双指在屏幕移动时的,歌词大小缩放
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">doScale</span>(MotionEvent event) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果歌词的模式为:拖动歌词模式</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode == DISPLAY_MODE_SEEK) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果是单指按下,在进行歌词上下滚动,然后按下另外一个手指,则把歌词模式从 拖动歌词模式 变为 缩放歌词模式</span>
            mDisplayMode = DISPLAY_MODE_SCALE;
            Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"change mode from DISPLAY_MODE_SEEK to DISPLAY_MODE_SCALE"</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// two pointer mode , scale font</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mIsFirstMove) {
            mDisplayMode = DISPLAY_MODE_SCALE;
            invalidate();
            mIsFirstMove = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//两个手指的x坐标和y坐标</span>
            setTwoPointerLocation(event);
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取歌词大小要缩放的比例</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> scaleSize = getScale(event);
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize:"</span> + scaleSize);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果缩放大小不等于0,进行缩放,重绘LrcView</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (scaleSize != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            setNewFontSize(scaleSize);
            invalidate();
        }
        setTwoPointerLocation(event);
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 处理单指在屏幕移动时,歌词上下滚动
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">doSeek</span>(MotionEvent event) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y = event.getY();<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指当前位置的y坐标</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> offsetY = y - mLastMotionY; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次按下的y坐标和目前移动手指位置的y坐标之差</span>
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果移动距离小于10,不做任何处理</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (Math.abs(offsetY) < mMinSeekFiredOffset) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将模式设置为拖动歌词模式</span>
        mDisplayMode = DISPLAY_MODE_SEEK;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> rowOffset = Math.abs((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) offsetY / mLrcFontSize); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//歌词要滚动的行数</span>

        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"move to new hightlightrow : "</span> + mHignlightRow + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" offsetY: "</span> + offsetY + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">" rowOffset:"</span> + rowOffset);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (offsetY < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指向上移动,歌词向下滚动</span>
            mHignlightRow += rowOffset;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为 当前高亮歌词 向下滚动rowOffset行后的歌词</span>
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (offsetY > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//手指向下移动,歌词向上滚动</span>
            mHignlightRow -= rowOffset;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为 当前高亮歌词 向上滚动rowOffset行后的歌词</span>
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为0和mHignlightRow中的较大值,即如果mHignlightRow < 0,mHignlightRow=0</span>
        mHignlightRow = Math.max(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, mHignlightRow);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置要高亮的歌词为0和mHignlightRow中的较小值,即如果mHignlight > RowmLrcRows.size()-1,mHignlightRow=mLrcRows.size()-1</span>
        mHignlightRow = Math.min(mHignlightRow, mLrcRows.size() - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果歌词要滚动的行数大于0,则重画LrcView</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (rowOffset > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            mLastMotionY = y;
            invalidate();
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置当前两个手指的x坐标和y坐标
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setTwoPointerLocation</span>(MotionEvent event) {
        mPointerOneLastMotion.x = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        mPointerOneLastMotion.y = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        mPointerTwoLastMotion.x = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        mPointerTwoLastMotion.y = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置缩放后的字体大小
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setNewFontSize</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> scaleSize) {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置歌词缩放后的的最新字体大小</span>
        mLrcFontSize += scaleSize;
        mLrcFontSize = Math.max(mLrcFontSize, mMinLrcFontSize);
        mLrcFontSize = Math.min(mLrcFontSize, mMaxLrcFontSize);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置歌词的最新字体大小</span>
        mSeekLineTextSize += scaleSize;
        mSeekLineTextSize = Math.max(mSeekLineTextSize, mMinSeekLineTextSize);
        mSeekLineTextSize = Math.min(mSeekLineTextSize, mMaxSeekLineTextSize);
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 获取歌词大小要缩放的比例
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getScale</span>(MotionEvent event) {
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize getScale"</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x0 = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y0 = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x1 = event.getX(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> y1 = event.getY(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> maxOffset = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// max offset between x or y axis,used to decide scale size</span>

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> zoomin = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次双指之间的x坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> oldXOffset = Math.abs(mPointerOneLastMotion.x - mPointerTwoLastMotion.x);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第二次双指之间的x坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> newXoffset = Math.abs(x1 - x0);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第一次双指之间的y坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> oldYOffset = Math.abs(mPointerOneLastMotion.y - mPointerTwoLastMotion.y);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第二次双指之间的y坐标的差距</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> newYoffset = Math.abs(y1 - y0);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//双指移动之后,判断双指之间移动的最大差距</span>
        maxOffset = Math.max(Math.abs(newXoffset - oldXOffset), Math.abs(newYoffset - oldYOffset));
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果x坐标移动的多一些</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (maxOffset == Math.abs(newXoffset - oldXOffset)) {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果第二次双指之间的x坐标的差距大于第一次双指之间的x坐标的差距则是放大,反之则缩小</span>
            zoomin = newXoffset > oldXOffset ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        }
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果y坐标移动的多一些</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//如果第二次双指之间的y坐标的差距大于第一次双指之间的y坐标的差距则是放大,反之则缩小</span>
            zoomin = newYoffset > oldYOffset ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
        }
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"scaleSize maxOffset:"</span> + maxOffset);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (zoomin) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (maxOffset / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//放大双指之间移动的最大差距的1/10</span>
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> -(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) (maxOffset / <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//缩小双指之间移动的最大差距的1/10</span>
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 设置歌词行集合
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> lrcRows
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setLrc</span>(List<LrcRow> lrcRows) {
        mLrcRows = lrcRows;
        invalidate();
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 播放的时候调用该方法滚动歌词,高亮正在播放的那句歌词
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> time
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">seekLrcToTime</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> time) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mLrcRows == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> || mLrcRows.size() == <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mDisplayMode != DISPLAY_MODE_NORMAL) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
        }
        Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"seekLrcToTime:"</span> + time);

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i < mLrcRows.size(); i++) {
            LrcRow current = mLrcRows.get(i);
            LrcRow next = i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> == mLrcRows.size() ? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> : mLrcRows.get(i + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
            <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
             *  正在播放的时间大于current行的歌词的时间而小于next行歌词的时间, 设置要高亮的行为current行
             *  正在播放的时间大于current行的歌词,而current行为最后一句歌词时,设置要高亮的行为current行
             */</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((time >= current.time && next != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && time < next.time)
                    || (time > current.time && next == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>)){
                seekLrc(i, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>;
            }
        }
    }
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li><li style="box-sizing: border-box; padding: 0px 5px;">168</li><li style="box-sizing: border-box; padding: 0px 5px;">169</li><li style="box-sizing: border-box; padding: 0px 5px;">170</li><li style="box-sizing: border-box; padding: 0px 5px;">171</li><li style="box-sizing: border-box; padding: 0px 5px;">172</li><li style="box-sizing: border-box; padding: 0px 5px;">173</li><li style="box-sizing: border-box; padding: 0px 5px;">174</li><li style="box-sizing: border-box; padding: 0px 5px;">175</li><li style="box-sizing: border-box; padding: 0px 5px;">176</li><li style="box-sizing: border-box; padding: 0px 5px;">177</li><li style="box-sizing: border-box; padding: 0px 5px;">178</li><li style="box-sizing: border-box; padding: 0px 5px;">179</li><li style="box-sizing: border-box; padding: 0px 5px;">180</li><li style="box-sizing: border-box; padding: 0px 5px;">181</li><li style="box-sizing: border-box; padding: 0px 5px;">182</li><li style="box-sizing: border-box; padding: 0px 5px;">183</li><li style="box-sizing: border-box; padding: 0px 5px;">184</li><li style="box-sizing: border-box; padding: 0px 5px;">185</li><li style="box-sizing: border-box; padding: 0px 5px;">186</li><li style="box-sizing: border-box; padding: 0px 5px;">187</li><li style="box-sizing: border-box; padding: 0px 5px;">188</li><li style="box-sizing: border-box; padding: 0px 5px;">189</li><li style="box-sizing: border-box; padding: 0px 5px;">190</li><li style="box-sizing: border-box; padding: 0px 5px;">191</li><li style="box-sizing: border-box; padding: 0px 5px;">192</li><li style="box-sizing: border-box; padding: 0px 5px;">193</li><li style="box-sizing: border-box; padding: 0px 5px;">194</li><li style="box-sizing: border-box; padding: 0px 5px;">195</li><li style="box-sizing: border-box; padding: 0px 5px;">196</li><li style="box-sizing: border-box; padding: 0px 5px;">197</li><li style="box-sizing: border-box; padding: 0px 5px;">198</li><li style="box-sizing: border-box; padding: 0px 5px;">199</li><li style="box-sizing: border-box; padding: 0px 5px;">200</li><li style="box-sizing: border-box; padding: 0px 5px;">201</li><li style="box-sizing: border-box; padding: 0px 5px;">202</li><li style="box-sizing: border-box; padding: 0px 5px;">203</li><li style="box-sizing: border-box; padding: 0px 5px;">204</li><li style="box-sizing: border-box; padding: 0px 5px;">205</li><li style="box-sizing: border-box; padding: 0px 5px;">206</li><li style="box-sizing: border-box; padding: 0px 5px;">207</li><li style="box-sizing: border-box; padding: 0px 5px;">208</li><li style="box-sizing: border-box; padding: 0px 5px;">209</li><li style="box-sizing: border-box; padding: 0px 5px;">210</li><li style="box-sizing: border-box; padding: 0px 5px;">211</li><li style="box-sizing: border-box; padding: 0px 5px;">212</li><li style="box-sizing: border-box; padding: 0px 5px;">213</li><li style="box-sizing: border-box; padding: 0px 5px;">214</li><li style="box-sizing: border-box; padding: 0px 5px;">215</li><li style="box-sizing: border-box; padding: 0px 5px;">216</li><li style="box-sizing: border-box; padding: 0px 5px;">217</li><li style="box-sizing: border-box; padding: 0px 5px;">218</li><li style="box-sizing: border-box; padding: 0px 5px;">219</li><li style="box-sizing: border-box; padding: 0px 5px;">220</li><li style="box-sizing: border-box; padding: 0px 5px;">221</li><li style="box-sizing: border-box; padding: 0px 5px;">222</li><li style="box-sizing: border-box; padding: 0px 5px;">223</li><li style="box-sizing: border-box; padding: 0px 5px;">224</li><li style="box-sizing: border-box; padding: 0px 5px;">225</li><li style="box-sizing: border-box; padding: 0px 5px;">226</li><li style="box-sizing: border-box; padding: 0px 5px;">227</li><li style="box-sizing: border-box; padding: 0px 5px;">228</li><li style="box-sizing: border-box; padding: 0px 5px;">229</li><li style="box-sizing: border-box; padding: 0px 5px;">230</li><li style="box-sizing: border-box; padding: 0px 5px;">231</li><li style="box-sizing: border-box; padding: 0px 5px;">232</li><li style="box-sizing: border-box; padding: 0px 5px;">233</li><li style="box-sizing: border-box; padding: 0px 5px;">234</li><li style="box-sizing: border-box; padding: 0px 5px;">235</li><li style="box-sizing: border-box; padding: 0px 5px;">236</li><li style="box-sizing: border-box; padding: 0px 5px;">237</li><li style="box-sizing: border-box; padding: 0px 5px;">238</li><li style="box-sizing: border-box; padding: 0px 5px;">239</li><li style="box-sizing: border-box; padding: 0px 5px;">240</li><li style="box-sizing: border-box; padding: 0px 5px;">241</li><li style="box-sizing: border-box; padding: 0px 5px;">242</li><li style="box-sizing: border-box; padding: 0px 5px;">243</li><li style="box-sizing: border-box; padding: 0px 5px;">244</li><li style="box-sizing: border-box; padding: 0px 5px;">245</li><li style="box-sizing: border-box; padding: 0px 5px;">246</li><li style="box-sizing: border-box; padding: 0px 5px;">247</li><li style="box-sizing: border-box; padding: 0px 5px;">248</li><li style="box-sizing: border-box; padding: 0px 5px;">249</li><li style="box-sizing: border-box; padding: 0px 5px;">250</li><li style="box-sizing: border-box; padding: 0px 5px;">251</li><li style="box-sizing: border-box; padding: 0px 5px;">252</li><li style="box-sizing: border-box; padding: 0px 5px;">253</li><li style="box-sizing: border-box; padding: 0px 5px;">254</li><li style="box-sizing: border-box; padding: 0px 5px;">255</li><li style="box-sizing: border-box; padding: 0px 5px;">256</li><li style="box-sizing: border-box; padding: 0px 5px;">257</li><li style="box-sizing: border-box; padding: 0px 5px;">258</li><li style="box-sizing: border-box; padding: 0px 5px;">259</li><li style="box-sizing: border-box; padding: 0px 5px;">260</li><li style="box-sizing: border-box; padding: 0px 5px;">261</li><li style="box-sizing: border-box; padding: 0px 5px;">262</li><li style="box-sizing: border-box; padding: 0px 5px;">263</li><li style="box-sizing: border-box; padding: 0px 5px;">264</li><li style="box-sizing: border-box; padding: 0px 5px;">265</li><li style="box-sizing: border-box; padding: 0px 5px;">266</li><li style="box-sizing: border-box; padding: 0px 5px;">267</li><li style="box-sizing: border-box; padding: 0px 5px;">268</li><li style="box-sizing: border-box; padding: 0px 5px;">269</li><li style="box-sizing: border-box; padding: 0px 5px;">270</li><li style="box-sizing: border-box; padding: 0px 5px;">271</li><li style="box-sizing: border-box; padding: 0px 5px;">272</li><li style="box-sizing: border-box; padding: 0px 5px;">273</li><li style="box-sizing: border-box; padding: 0px 5px;">274</li><li style="box-sizing: border-box; padding: 0px 5px;">275</li><li style="box-sizing: border-box; padding: 0px 5px;">276</li><li style="box-sizing: border-box; padding: 0px 5px;">277</li><li style="box-sizing: border-box; padding: 0px 5px;">278</li><li style="box-sizing: border-box; padding: 0px 5px;">279</li><li style="box-sizing: border-box; padding: 0px 5px;">280</li><li style="box-sizing: border-box; padding: 0px 5px;">281</li><li style="box-sizing: border-box; padding: 0px 5px;">282</li><li style="box-sizing: border-box; padding: 0px 5px;">283</li><li style="box-sizing: border-box; padding: 0px 5px;">284</li><li style="box-sizing: border-box; padding: 0px 5px;">285</li><li style="box-sizing: border-box; padding: 0px 5px;">286</li><li style="box-sizing: border-box; padding: 0px 5px;">287</li><li style="box-sizing: border-box; padding: 0px 5px;">288</li><li style="box-sizing: border-box; padding: 0px 5px;">289</li><li style="box-sizing: border-box; padding: 0px 5px;">290</li><li style="box-sizing: border-box; padding: 0px 5px;">291</li><li style="box-sizing: border-box; padding: 0px 5px;">292</li><li style="box-sizing: border-box; padding: 0px 5px;">293</li><li style="box-sizing: border-box; padding: 0px 5px;">294</li><li style="box-sizing: border-box; padding: 0px 5px;">295</li><li style="box-sizing: border-box; padding: 0px 5px;">296</li><li style="box-sizing: border-box; padding: 0px 5px;">297</li><li style="box-sizing: border-box; padding: 0px 5px;">298</li><li style="box-sizing: border-box; padding: 0px 5px;">299</li><li style="box-sizing: border-box; padding: 0px 5px;">300</li><li style="box-sizing: border-box; padding: 0px 5px;">301</li><li style="box-sizing: border-box; padding: 0px 5px;">302</li><li style="box-sizing: border-box; padding: 0px 5px;">303</li><li style="box-sizing: border-box; padding: 0px 5px;">304</li><li style="box-sizing: border-box; padding: 0px 5px;">305</li><li style="box-sizing: border-box; padding: 0px 5px;">306</li><li style="box-sizing: border-box; padding: 0px 5px;">307</li><li style="box-sizing: border-box; padding: 0px 5px;">308</li><li style="box-sizing: border-box; padding: 0px 5px;">309</li><li style="box-sizing: border-box; padding: 0px 5px;">310</li><li style="box-sizing: border-box; padding: 0px 5px;">311</li><li style="box-sizing: border-box; padding: 0px 5px;">312</li><li style="box-sizing: border-box; padding: 0px 5px;">313</li><li style="box-sizing: border-box; padding: 0px 5px;">314</li><li style="box-sizing: border-box; padding: 0px 5px;">315</li><li style="box-sizing: border-box; padding: 0px 5px;">316</li><li style="box-sizing: border-box; padding: 0px 5px;">317</li><li style="box-sizing: border-box; padding: 0px 5px;">318</li><li style="box-sizing: border-box; padding: 0px 5px;">319</li><li style="box-sizing: border-box; padding: 0px 5px;">320</li><li style="box-sizing: border-box; padding: 0px 5px;">321</li><li style="box-sizing: border-box; padding: 0px 5px;">322</li><li style="box-sizing: border-box; padding: 0px 5px;">323</li><li style="box-sizing: border-box; padding: 0px 5px;">324</li><li style="box-sizing: border-box; padding: 0px 5px;">325</li><li style="box-sizing: border-box; padding: 0px 5px;">326</li><li style="box-sizing: border-box; padding: 0px 5px;">327</li><li style="box-sizing: border-box; padding: 0px 5px;">328</li><li style="box-sizing: border-box; padding: 0px 5px;">329</li><li style="box-sizing: border-box; padding: 0px 5px;">330</li><li style="box-sizing: border-box; padding: 0px 5px;">331</li><li style="box-sizing: border-box; padding: 0px 5px;">332</li><li style="box-sizing: border-box; padding: 0px 5px;">333</li><li style="box-sizing: border-box; padding: 0px 5px;">334</li><li style="box-sizing: border-box; padding: 0px 5px;">335</li><li style="box-sizing: border-box; padding: 0px 5px;">336</li><li style="box-sizing: border-box; padding: 0px 5px;">337</li><li style="box-sizing: border-box; padding: 0px 5px;">338</li><li style="box-sizing: border-box; padding: 0px 5px;">339</li><li style="box-sizing: border-box; padding: 0px 5px;">340</li><li style="box-sizing: border-box; padding: 0px 5px;">341</li><li style="box-sizing: border-box; padding: 0px 5px;">342</li><li style="box-sizing: border-box; padding: 0px 5px;">343</li><li style="box-sizing: border-box; padding: 0px 5px;">344</li><li style="box-sizing: border-box; padding: 0px 5px;">345</li><li style="box-sizing: border-box; padding: 0px 5px;">346</li><li style="box-sizing: border-box; padding: 0px 5px;">347</li><li style="box-sizing: border-box; padding: 0px 5px;">348</li><li style="box-sizing: border-box; padding: 0px 5px;">349</li><li style="box-sizing: border-box; padding: 0px 5px;">350</li><li style="box-sizing: border-box; padding: 0px 5px;">351</li><li style="box-sizing: border-box; padding: 0px 5px;">352</li><li style="box-sizing: border-box; padding: 0px 5px;">353</li><li style="box-sizing: border-box; padding: 0px 5px;">354</li><li style="box-sizing: border-box; padding: 0px 5px;">355</li><li style="box-sizing: border-box; padding: 0px 5px;">356</li><li style="box-sizing: border-box; padding: 0px 5px;">357</li><li style="box-sizing: border-box; padding: 0px 5px;">358</li><li style="box-sizing: border-box; padding: 0px 5px;">359</li><li style="box-sizing: border-box; padding: 0px 5px;">360</li><li style="box-sizing: border-box; padding: 0px 5px;">361</li><li style="box-sizing: border-box; padding: 0px 5px;">362</li><li style="box-sizing: border-box; padding: 0px 5px;">363</li><li style="box-sizing: border-box; padding: 0px 5px;">364</li><li style="box-sizing: border-box; padding: 0px 5px;">365</li><li style="box-sizing: border-box; padding: 0px 5px;">366</li><li style="box-sizing: border-box; padding: 0px 5px;">367</li><li style="box-sizing: border-box; padding: 0px 5px;">368</li><li style="box-sizing: border-box; padding: 0px 5px;">369</li><li style="box-sizing: border-box; padding: 0px 5px;">370</li><li style="box-sizing: border-box; padding: 0px 5px;">371</li><li style="box-sizing: border-box; padding: 0px 5px;">372</li><li style="box-sizing: border-box; padding: 0px 5px;">373</li><li style="box-sizing: border-box; padding: 0px 5px;">374</li><li style="box-sizing: border-box; padding: 0px 5px;">375</li><li style="box-sizing: border-box; padding: 0px 5px;">376</li><li style="box-sizing: border-box; padding: 0px 5px;">377</li><li style="box-sizing: border-box; padding: 0px 5px;">378</li><li style="box-sizing: border-box; padding: 0px 5px;">379</li><li style="box-sizing: border-box; padding: 0px 5px;">380</li><li style="box-sizing: border-box; padding: 0px 5px;">381</li><li style="box-sizing: border-box; padding: 0px 5px;">382</li><li style="box-sizing: border-box; padding: 0px 5px;">383</li><li style="box-sizing: border-box; padding: 0px 5px;">384</li><li style="box-sizing: border-box; padding: 0px 5px;">385</li><li style="box-sizing: border-box; padding: 0px 5px;">386</li><li style="box-sizing: border-box; padding: 0px 5px;">387</li><li style="box-sizing: border-box; padding: 0px 5px;">388</li><li style="box-sizing: border-box; padding: 0px 5px;">389</li><li style="box-sizing: border-box; padding: 0px 5px;">390</li><li style="box-sizing: border-box; padding: 0px 5px;">391</li><li style="box-sizing: border-box; padding: 0px 5px;">392</li><li style="box-sizing: border-box; padding: 0px 5px;">393</li><li style="box-sizing: border-box; padding: 0px 5px;">394</li><li style="box-sizing: border-box; padding: 0px 5px;">395</li><li style="box-sizing: border-box; padding: 0px 5px;">396</li><li style="box-sizing: border-box; padding: 0px 5px;">397</li><li style="box-sizing: border-box; padding: 0px 5px;">398</li><li style="box-sizing: border-box; padding: 0px 5px;">399</li><li style="box-sizing: border-box; padding: 0px 5px;">400</li><li style="box-sizing: border-box; padding: 0px 5px;">401</li><li style="box-sizing: border-box; padding: 0px 5px;">402</li><li style="box-sizing: border-box; padding: 0px 5px;">403</li><li style="box-sizing: border-box; padding: 0px 5px;">404</li><li style="box-sizing: border-box; padding: 0px 5px;">405</li><li style="box-sizing: border-box; padding: 0px 5px;">406</li><li style="box-sizing: border-box; padding: 0px 5px;">407</li><li style="box-sizing: border-box; padding: 0px 5px;">408</li><li style="box-sizing: border-box; padding: 0px 5px;">409</li><li style="box-sizing: border-box; padding: 0px 5px;">410</li><li style="box-sizing: border-box; padding: 0px 5px;">411</li><li style="box-sizing: border-box; padding: 0px 5px;">412</li><li style="box-sizing: border-box; padding: 0px 5px;">413</li><li style="box-sizing: border-box; padding: 0px 5px;">414</li><li style="box-sizing: border-box; padding: 0px 5px;">415</li><li style="box-sizing: border-box; padding: 0px 5px;">416</li><li style="box-sizing: border-box; padding: 0px 5px;">417</li><li style="box-sizing: border-box; padding: 0px 5px;">418</li><li style="box-sizing: border-box; padding: 0px 5px;">419</li><li style="box-sizing: border-box; padding: 0px 5px;">420</li><li style="box-sizing: border-box; padding: 0px 5px;">421</li><li style="box-sizing: border-box; padding: 0px 5px;">422</li><li style="box-sizing: border-box; padding: 0px 5px;">423</li><li style="box-sizing: border-box; padding: 0px 5px;">424</li><li style="box-sizing: border-box; padding: 0px 5px;">425</li><li style="box-sizing: border-box; padding: 0px 5px;">426</li><li style="box-sizing: border-box; padding: 0px 5px;">427</li><li style="box-sizing: border-box; padding: 0px 5px;">428</li><li style="box-sizing: border-box; padding: 0px 5px;">429</li><li style="box-sizing: border-box; padding: 0px 5px;">430</li><li style="box-sizing: border-box; padding: 0px 5px;">431</li><li style="box-sizing: border-box; padding: 0px 5px;">432</li><li style="box-sizing: border-box; padding: 0px 5px;">433</li><li style="box-sizing: border-box; padding: 0px 5px;">434</li><li style="box-sizing: border-box; padding: 0px 5px;">435</li><li style="box-sizing: border-box; padding: 0px 5px;">436</li><li style="box-sizing: border-box; padding: 0px 5px;">437</li><li style="box-sizing: border-box; padding: 0px 5px;">438</li><li style="box-sizing: border-box; padding: 0px 5px;">439</li><li style="box-sizing: border-box; padding: 0px 5px;">440</li><li style="box-sizing: border-box; padding: 0px 5px;">441</li><li style="box-sizing: border-box; padding: 0px 5px;">442</li><li style="box-sizing: border-box; padding: 0px 5px;">443</li><li style="box-sizing: border-box; padding: 0px 5px;">444</li><li style="box-sizing: border-box; padding: 0px 5px;">445</li><li style="box-sizing: border-box; padding: 0px 5px;">446</li><li style="box-sizing: border-box; padding: 0px 5px;">447</li><li style="box-sizing: border-box; padding: 0px 5px;">448</li><li style="box-sizing: border-box; padding: 0px 5px;">449</li><li style="box-sizing: border-box; padding: 0px 5px;">450</li><li style="box-sizing: border-box; padding: 0px 5px;">451</li><li style="box-sizing: border-box; padding: 0px 5px;">452</li><li style="box-sizing: border-box; padding: 0px 5px;">453</li><li style="box-sizing: border-box; padding: 0px 5px;">454</li><li style="box-sizing: border-box; padding: 0px 5px;">455</li><li style="box-sizing: border-box; padding: 0px 5px;">456</li><li style="box-sizing: border-box; padding: 0px 5px;">457</li><li style="box-sizing: border-box; padding: 0px 5px;">458</li><li style="box-sizing: border-box; padding: 0px 5px;">459</li><li style="box-sizing: border-box; padding: 0px 5px;">460</li><li style="box-sizing: border-box; padding: 0px 5px;">461</li><li style="box-sizing: border-box; padding: 0px 5px;">462</li><li style="box-sizing: border-box; padding: 0px 5px;">463</li><li style="box-sizing: border-box; padding: 0px 5px;">464</li><li style="box-sizing: border-box; padding: 0px 5px;">465</li><li style="box-sizing: border-box; padding: 0px 5px;">466</li><li style="box-sizing: border-box; padding: 0px 5px;">467</li><li style="box-sizing: border-box; padding: 0px 5px;">468</li><li style="box-sizing: border-box; padding: 0px 5px;">469</li><li style="box-sizing: border-box; padding: 0px 5px;">470</li></ul>

以上就是自定义LrcView的全部内容,下面将该自定义LrcView放在布局文件activity_main.xml中去显示出来。

activity_main.xml的代码如下所示:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><RelativeLayout xmlns:android=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"http://schemas.android.com/apk/res/android"</span>
    android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span>
    android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"match_parent"</span> >

    <<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.oyp</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.lrc</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.view</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.impl</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.LrcView</span>
        android:id=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"@+id/lrcView"</span>
        android:layout_width=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>
        android:layout_height=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"wrap_content"</span>
        />
</RelativeLayout></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

MainActivity代码如下所示:

然后通过MainActivity来加载该布局,并在MainActivity中播放音乐,MainActivity的代码如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.oyp.lrc;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.app.Activity;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.media.MediaPlayer;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.media.MediaPlayer.OnCompletionListener;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.media.MediaPlayer.OnPreparedListener;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.os.Bundle;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> android.util.Log;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcBuilder;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcView;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.ILrcViewListener;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.impl.DefaultLrcBuilder;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.oyp.lrc.view.impl.LrcRow;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.BufferedReader;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.IOException;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.io.InputStreamReader;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.List;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.Timer;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> java.util.TimerTask;

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MainActivity</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Activity</span> {</span>

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> String TAG = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"MainActivity"</span>;

    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//自定义LrcView,用来展示歌词</span>
    ILrcView mLrcView;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//更新歌词的频率,每秒更新一次</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> mPalyTimerDuration = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1000</span>;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//更新歌词的定时器</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> Timer mTimer;
    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//更新歌词的定时任务</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> TimerTask mTask;

    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCreate</span>(Bundle savedInstanceState) {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onCreate(savedInstanceState);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取自定义的LrcView</span>
        setContentView(R.layout.activity_main);
        mLrcView=(ILrcView)findViewById(R.id.lrcView);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//从assets目录下读取歌词文件内容</span>
        String lrc = getFromAssets(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.lrc"</span>);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析歌词构造器</span>
        ILrcBuilder builder = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> DefaultLrcBuilder();
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解析歌词返回LrcRow集合</span>
        List<LrcRow> rows = builder.getLrcRows(lrc);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//将得到的歌词集合传给mLrcView用来展示</span>
        mLrcView.setLrc(rows);

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//开始播放歌曲并同步展示歌词</span>
        beginLrcPlay();

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置自定义的LrcView上下拖动歌词时监听</span>
        mLrcView.setListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ILrcViewListener() {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//当歌词被用户上下拖动的时候回调该方法,从高亮的那一句歌词开始播放</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onLrcSeeked</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> newPosition, LrcRow row) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPlayer != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                    Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"onLrcSeeked:"</span> + row.time);
                    mPlayer.seekTo((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>) row.time);
                }
            }
        });
    }

    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">protected</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onDestroy</span>() {
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onDestroy();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPlayer != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
            mPlayer.stop();
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 从assets目录下读取歌词文件内容
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> fileName
     *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span>
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getFromAssets</span>(String fileName){
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            InputStreamReader inputReader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> InputStreamReader( getResources().getAssets().open(fileName) );
            BufferedReader bufReader = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> BufferedReader(inputReader);
            String line=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
            String result=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>((line = bufReader.readLine()) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(line.trim().equals(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>))
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">continue</span>;
                result += line + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"\r\n"</span>;
            }
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> result;
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            e.printStackTrace();
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">""</span>;
    }

    MediaPlayer mPlayer;

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 开始播放歌曲并同步展示歌词
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">beginLrcPlay</span>(){
        mPlayer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> MediaPlayer();
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            mPlayer.setDataSource(getAssets().openFd(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"test.mp3"</span>).getFileDescriptor());
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//准备播放歌曲监听</span>
            mPlayer.setOnPreparedListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnPreparedListener() {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//准备完毕</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onPrepared</span>(MediaPlayer mp) {
                    mp.start();
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mTimer == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
                        mTimer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Timer();
                        mTask = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LrcTask();
                        mTimer.scheduleAtFixedRate(mTask, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, mPalyTimerDuration);
                    }
                }
            });
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//歌曲播放完毕监听</span>
            mPlayer.setOnCompletionListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnCompletionListener() {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onCompletion</span>(MediaPlayer mp) {
                    stopLrcPlay();
                }
            });
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//准备播放歌曲</span>
            mPlayer.prepare();
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//开始播放歌曲</span>
            mPlayer.start();
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IllegalArgumentException e) {
            e.printStackTrace();
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IllegalStateException e) {
            e.printStackTrace();
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (IOException e) {
            e.printStackTrace();
        }

    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 停止展示歌曲
     */</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">stopLrcPlay</span>(){
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(mTimer != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>){
            mTimer.cancel();
            mTimer = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        }
    }

    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
     * 展示歌曲的定时任务
     */</span>
    class LrcTask extends TimerTask{
        <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//获取歌曲播放的位置</span>
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> timePassed = mPlayer.getCurrentPosition();
            MainActivity.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.runOnUiThread(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Runnable() {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">run</span>() {
                    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//滚动歌词</span>
                    mLrcView.seekLrcToTime(timePassed);
                }
            });

        }
    };
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li><li style="box-sizing: border-box; padding: 0px 5px;">164</li><li style="box-sizing: border-box; padding: 0px 5px;">165</li><li style="box-sizing: border-box; padding: 0px 5px;">166</li><li style="box-sizing: border-box; padding: 0px 5px;">167</li></ul>

下面是项目的结构图。 
这里写图片描述

四、项目源码地址

版权声明:本文为【欧阳鹏】原创文章,欢迎转载,转载请注明出处! 【http://blog.csdn.net/ouyang_peng/article/details/50813419

作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!  
转载请保留原文地址: 
http://blog.csdn.net/ouyang_peng/article/details/50813419

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值