/** To change this template, choose Tools | Templates
* and open the template in the editor.*/packagecom.hadeslee.yoyoplayer.lyric;importcom.hadeslee.yoyoplayer.playlist.PlayListItem;importcom.hadeslee.yoyoplayer.util.Config;importcom.hadeslee.yoyoplayer.util.Util;importjava.awt.Color;importjava.awt.Graphics;importjava.awt.Graphics2D;importjava.awt.LinearGradientPaint;importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileFilter;importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputStreamWriter;importjava.io.Serializable;importjava.io.StringReader;importjava.util.ArrayList;importjava.util.Collections;importjava.util.Comparator;importjava.util.List;importjava.util.logging.Level;importjava.util.logging.Logger;importjava.util.regex.Matcher;importjava.util.regex.Pattern;/*** 表示一首歌的歌词对象,它可以以某种方式来画自己
*@authorhadeslee*/publicclassLyricimplementsSerializable {privatestaticfinallongserialVersionUID=20071125L;privatestaticLogger log=Logger.getLogger(Lyric.class.getName());privateintwidth;//表示歌词的显示区域的宽度privateintheight;//表示歌词的显示区域的高度privatelongtime;//表示当前的时间是多少了。以毫秒为单位privatelongtempTime;//表示一个暂时的时间,用于拖动的时候,确定应该到哪了privateListlist=newArrayList();//里面装的是所有的句子privatebooleanisMoving;//是否正在被拖动privateintcurrentIndex;//当前正在显示的歌词的下标privatebooleaninitDone;//是否初始化完毕了privatetransientPlayListItem info;//有关于这首歌的信息privatetransientFile file;//该歌词所存在文件privatebooleanenabled=true;//是否起用了该对象,默认是起用的privatelongduring=Integer.MAX_VALUE;//这首歌的长度/*** 用ID3V1标签的字节和歌名来初始化歌词
* 歌词将自动在本地或者网络上搜索相关的歌词并建立关联
* 本地搜索将硬编码为user.home文件夹下面的Lyrics文件夹
* 以后改为可以手动设置.
*@paramsongName 歌名
*@paramdata ID3V1的数据*/publicLyric(finalPlayListItem info) {this.info=info;this.during=info.getLength()*1000;this.file=info.getLyricFile();
log.info("传进来的歌名是:"+info.toString());//只要有关联好了的,就不用搜索了直接用就是了if(file!=null) {
log.log(Level.INFO,"不用找了,直接关联到的歌词是:"+file);
init(file);
initDone=true;return;
}else{//否则就起一个线程去找了,先是本地找,然后再是网络上找newThread() {publicvoidrun() {
doInit(info);
initDone=true;
}
}.start();
}
}/*** 读取某个指定的歌词文件,这个构造函数一般用于
* 拖放歌词文件到歌词窗口时调用的,拖放以后,两个自动关联
*@paramfile 歌词文件
*@paraminfo 歌曲信息*/publicLyric(File file, PlayListItem info) {this.file=file;this.info=info;
init(file);
initDone=true;
}/*** 根据歌词内容和播放项构造一个
* 歌词对象
*@paramlyric 歌词内容
*@paraminfo 播放项*/publicLyric(String lyric, PlayListItem info) {this.info=info;this.init(lyric);
initDone=true;
}privatevoiddoInit(PlayListItem info) {
init(info);
Sentence temp=null;//这个时候就要去网络上找了if(list.size()==1) {
temp=list.remove(0);try{
String lyric=Util.getLyric(info);if(lyric!=null) {
init(lyric);
saveLyric(lyric, info);
}else{//如果网络也没有找到,就要加回去了list.add(temp);
}
}catch(IOException ex) {
Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE,null, ex);//如果抛了任何异常,也要加回去了list.add(temp);
}
}
}/*** 把下载到的歌词保存起来,免得下次再去找
*@paramlyric 歌词内容
*@paraminfo 歌的信息*/privatevoidsaveLyric(String lyric, PlayListItem info) {try{//如果歌手不为空,则以歌手名+歌曲名为最好组合String name=info.getFormattedName()+".lrc";//File dir = new File(Config.HOME, "Lyrics" + File.separator);File dir=Config.getConfig().getSaveLyricDir();
dir.mkdirs();
file=newFile(dir, name);
BufferedWriter bw=newBufferedWriter(newOutputStreamWriter(newFileOutputStream(file),"GBK"));
bw.write(lyric);
bw.close();
info.setLyricFile(file);
log.info("保存完毕,保存在:"+file);
}catch(Exception exe) {
log.log(Level.SEVERE,"保存歌词出错", exe);
}
}/*** 设置此歌词是否起用了,否则就不动了
*@paramb 是否起用*/publicvoidsetEnabled(booleanb) {this.enabled=b;
}/*** 得到此歌词保存的地方
*@return文件*/publicFile getLyricFile() {returnfile;
}/*** 调整整体的时间,比如歌词统一快多少
* 或者歌词统一慢多少,为正说明要快,为负说明要慢
*@paramtime 要调的时间,单位是毫秒*/publicvoidadjustTime(inttime) {//如果是只有一个显示的,那就说明没有什么效对的意义了,直接返回if(list.size()==1) {return;
}for(Sentence s : list) {
s.setFromTime(s.getFromTime()-time);
s.setToTime(s.getToTime()-time);
}
}/*** 根据一个文件夹,和一个歌曲的信息
* 从本地搜到最匹配的歌词
*@paramdir 目录
*@paraminfo 歌曲信息
*@return歌词文件*/privateFile getMathedLyricFile(File dir, PlayListItem info) {
File matched=null;//已经匹配的文件File[] fs=dir.listFiles(newFileFilter() {publicbooleanaccept(File pathname) {returnpathname.getName().toLowerCase().endsWith(".lrc");
}
});for(File f : fs) {//全部匹配或者部分匹配都行if(matchAll(info, f)||matchSongName(info, f)) {
matched=f;break;
}
}returnmatched;
}/*** 根据歌的信息去初始化,这个时候
* 可能在本地找到歌词文件,也可能要去网络上搜索了
*@paraminfo 歌曲信息*/privatevoidinit(PlayListItem info) {
File matched=null;for(File dir : Config.getConfig().getSearchLyricDirs()) {
log.log(Level.FINE,"正在搜索文件夹:"+dir);//得到歌曲信息后,先本地搜索,先搜索HOME文件夹//如果还不存在的话,那建一个目录,然后直接退出不管了if(!dir.exists()) {
dir.mkdirs();
}
matched=getMathedLyricFile(dir, info);//当搜索到了,就退出if(matched!=null) {break;
}
}
log.info("找到的是:"+matched);if(matched!=null) {
info.setLyricFile(matched);
file=matched;
init(matched);
}else{
init("");
}
}/*** 根据文件来初始化
*@paramfile 文件*/privatevoidinit(File file) {
BufferedReader br=null;try{
br=newBufferedReader(newInputStreamReader(newFileInputStream(file),"GBK"));
StringBuilder sb=newStringBuilder();
String temp=null;while((temp=br.readLine())!=null) {
sb.append(temp).append("\n");
}
init(sb.toString());
}catch(Exception ex) {
Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE,null, ex);
}finally{try{
br.close();
}catch(Exception ex) {
Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE,null, ex);
}
}
}/*** 是否完全匹配,完全匹配是指直接对应到ID3V1的标签,
* 如果一样,则完全匹配了,完全匹配的LRC的文件格式是:
* 阿木 - 有一种爱叫放手.lrc
*@paraminfo 歌曲信息
*@paramfile 侯选文件
*@return是否合格*/privatebooleanmatchAll(PlayListItem info, File file) {
String name=info.getFormattedName();
String fn=file.getName().substring(0, file.getName().lastIndexOf("."));if(name.equals(fn)) {returntrue;
}else{returnfalse;
}
}/*** 是否匹配了歌曲名
*@paraminfo 歌曲信息
*@paramfile 侯选文件
*@return是否合格*/privatebooleanmatchSongName(PlayListItem info, File file) {
String name=info.getFormattedName();
String rn=file.getName().substring(0, file.getName().lastIndexOf("."));if(name.equalsIgnoreCase(rn)||info.getTitle().equalsIgnoreCase(rn)) {returntrue;
}else{returnfalse;
}
}/*** 最重要的一个方法,它根据读到的歌词内容
* 进行初始化,比如把歌词一句一句分开并计算好时间
*@paramcontent 歌词内容*/privatevoidinit(String content) {//如果歌词的内容为空,则后面就不用执行了//直接显示歌曲名就可以了if(content==null||content.trim().equals("")) {
list.add(newSentence(info.getFormattedName(), Integer.MIN_VALUE, Integer.MAX_VALUE));return;
}try{
BufferedReader br=newBufferedReader(newStringReader(content));
String temp=null;while((temp=br.readLine())!=null) {
parseLine(temp.trim());
}
br.close();//读进来以后就排序了Collections.sort(list,newComparator() {publicintcompare(Sentence o1, Sentence o2) {return(int) (o1.getFromTime()-o2.getFromTime());
}
});//处理第一句歌词的起始情况,无论怎么样,加上歌名做为第一句歌词,并把它的//结尾为真正第一句歌词的开始if(list.size()==0) {
list.add(newSentence(info.getFormattedName(),0, Integer.MAX_VALUE));return;
}else{
Sentence first=list.get(0);
list.add(0,newSentence(info.getFormattedName(),0, first.getFromTime()));
}intsize=list.size();for(inti=0; i
Sentence next=null;if(i+1
next=list.get(i+1);
}
Sentence now=list.get(i);if(next!=null) {
now.setToTime(next.getFromTime()-1);
}
}//如果就是没有怎么办,那就只显示一句歌名了if(list.size()==1) {
list.get(0).setToTime(Integer.MAX_VALUE);
}else{
Sentence last=list.get(list.size()-1);
last.setToTime(info==null?Integer.MAX_VALUE : info.getLength()*1000+1000);
}
}catch(Exception ex) {
Logger.getLogger(Lyric.class.getName()).log(Level.SEVERE,null, ex);
}
}/*** 分析这一行的内容,根据这内容
* 以及标签的数量生成若干个Sentence对象
*@paramline 这一行*/privatevoidparseLine(String line) {if(line.equals("")) {return;
}
Matcher m=Pattern.compile("(?<=\\[).*?(?=\\])").matcher(line);
Listtemp=newArrayList();intlength=0;while(m.find()) {
String s=m.group();
temp.add(s);
length+=(s.length()+2);
}try{
String content=line.substring(length>line.length()?line.length() : length);if(Config.getConfig().isCutBlankChars()) {
content=content.trim();
}if(content.equals("")) {return;
}for(String s : temp) {longt=parseTime(s);if(t!=-1) {
list.add(newSentence(content, t));
}
}
}catch(Exception exe) {
}
}/*** 把如00:00.00这样的字符串转化成
* 毫秒数的时间,比如
* 01:10.34就是一分钟加上10秒再加上340毫秒
* 也就是返回70340毫秒
*@paramtime 字符串的时间
*@return此时间表示的毫秒*/privatelongparseTime(String time) {
String[] ss=time.split("\\:|\\.");//如果 是两位以后,就非法了if(ss.length<2) {return-1;
}elseif(ss.length==2) {//如果正好两位,就算分秒try{intmin=Integer.parseInt(ss[0]);intsec=Integer.parseInt(ss[1]);if(min<0||sec<0||sec>=60) {thrownewRuntimeException("数字不合法!");
}return(min*60+sec)*1000L;
}catch(Exception exe) {return-1;
}
}elseif(ss.length==3) {//如果正好三位,就算分秒,十毫秒try{intmin=Integer.parseInt(ss[0]);intsec=Integer.parseInt(ss[1]);intmm=Integer.parseInt(ss[2]);if(min<0||sec<0||sec>=60||mm<0||mm>99) {thrownewRuntimeException("数字不合法!");
}return(min*60+sec)*1000L+mm*10;
}catch(Exception exe) {return-1;
}
}else{//否则也非法return-1;
}
}/*** 设置其显示区域的高度
*@paramheight 高度*/publicvoidsetHeight(intheight) {this.height=height;
}/*** 设置其显示区域的宽度
*@paramwidth 宽度*/publicvoidsetWidth(intwidth) {this.width=width;
}/*** 设置时间
*@paramtime 时间*/publicvoidsetTime(longtime) {if(!isMoving) {
tempTime=this.time=time;
}
}/*** 得到是否初始化完成了
*@return是否完成*/publicbooleanisInitDone() {returninitDone;
}privatevoiddrawKaraoke(Graphics2D gd, Sentence now,intx,inty,longt) {intnowWidth=now.getContentWidth(gd);
Color gradient=null;//如果要渐入渐出才去求中间色,否则直接用高亮色画if(Config.getConfig().isLyricShadow()) {
gradient=now.getBestInColor(Config.getConfig().getLyricHilight(), Config.getConfig().getLyricForeground(), t);
}else{
gradient=Config.getConfig().getLyricHilight();
}if(Config.getConfig().isKaraoke()) {floatf=(t-now.getFromTime())*1.0f/(now.getToTime()-now.getFromTime());if(f>0.98f) {
f=0.98f;
}if(x==0) {
x=1;
}if(nowWidth==0) {
nowWidth=1;
}
gd.setPaint(newLinearGradientPaint(x, y, x+nowWidth, y,newfloat[]{f, f+0.01f},newColor[]{gradient, Config.getConfig().getLyricForeground()}));
}else{
gd.setPaint(gradient);
}
Util.drawString(gd, now.getContent(), x, y);
}/*** 自力更生,画出自己在水平方向的方法
* 这个做是为了更方便地把歌词显示在
* 任何想显示的地方
*@paramg 画笔*/publicsynchronizedvoiddrawH(Graphics g) {if(!enabled) {
Sentence sen=newSentence(info.getFormattedName());intx=(width-sen.getContentWidth(g))/2;inty=(height-sen.getContentHeight(g)+Config.getConfig().getV_SPACE())/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);return;
}//首先看是不是初始化完毕了if(!initDone) {
Sentence temp=newSentence("正在搜索歌词");intx=(width-temp.getContentWidth(g))/2;inty=(height-temp.getContentHeight(g))/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, temp.getContent(), x, y);return;
}//如果只存在一句的话,那就不要浪费那么多计算的时候了//直接画在中间就可以了if(list.size()==1) {
Sentence sen=list.get(0);intx=(width-sen.getContentWidth(g))/2;inty=(height-sen.getContentHeight(g)+Config.getConfig().getV_SPACE())/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);
}else{//取一个time的副本,以防止在一个方法里面产生两种time的情况longt=tempTime;
Graphics2D gd=(Graphics2D) g;intindex=getNowSentenceIndex(t);if(!isMoving) {
currentIndex=index;
}if(index==-1) {
Sentence sen=newSentence(info.getFormattedName(), Integer.MIN_VALUE, Integer.MAX_VALUE);intx=(width-sen.getContentWidth(g)-Config.getConfig().getH_SPACE())/2;inty=(height-sen.getContentHeight(g)+Config.getConfig().getV_SPACE())/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);return;
}
Sentence now=list.get(index);intnowWidth=now.getContentWidth(g)+Config.getConfig().getH_SPACE();intx=(width)/2-now.getHIncrease(g, t);inty=(height-now.getContentHeight(g))/2;this.drawKaraoke(gd, now, x, y, t);
gd.setPaint(Config.getConfig().getLyricForeground());inttempX=x;//画出中间那句之前的句子for(inti=index-1; i>=0; i--) {
Sentence sen=list.get(i);intwid=sen.getContentWidth(g)+Config.getConfig().getH_SPACE();
tempX=tempX-wid;if(tempX+wid<0) {break;
}if(Config.getConfig().isLyricShadow()) {if(i==index-1) {
gd.setPaint(sen.getBestOutColor(Config.getConfig().getLyricHilight(),
Config.getConfig().getLyricForeground(), time));
}else{
gd.setPaint(Config.getConfig().getLyricForeground());
}
}
Util.drawString(g, sen.getContent(), tempX, y);
}
gd.setPaint(Config.getConfig().getLyricForeground());
tempX=x;inttempWidth=nowWidth;//画出中间那句之后的句子for(inti=index+1; i
Sentence sen=list.get(i);
tempX=tempX+tempWidth;if(tempX>width) {break;
}
Util.drawString(g, sen.getContent(), tempX, y);
tempWidth=sen.getContentWidth(g)+Config.getConfig().getH_SPACE();
}
}
}/*** 得到这批歌词里面,最长的那一句的长度
*@return最长的长度*/publicintgetMaxWidth(Graphics g) {intmax=0;for(Sentence sen : list) {intw=sen.getContentWidth(g);if(w>max) {
max=w;
}
}returnmax;
}/*** 得到一句话的X座标,因为可能对齐方式有
* 多种,针对每种对齐方式,X的座标不一
* 定一样。
*@paramg 画笔
*@paramsen 要求的句子
*@return本句的X座标*/privateintgetSentenceX(Graphics g, Sentence sen) {intx=0;inti=Config.getConfig().getLyricAlignMode();switch(i) {caseConfig.LYRIC_CENTER_ALIGN:
x=(width-sen.getContentWidth(g))/2;break;caseConfig.LYRIC_LEFT_ALIGN:
x=0;break;caseConfig.LYRIC_RIGHT_ALIGN:
x=width-sen.getContentWidth(g);break;default://默认情况还是中间对齐x=(width-sen.getContentWidth(g))/2;break;
}returnx;
}/*** 画出自己在垂直方向上的过程
*@paramg 画笔*/publicsynchronizedvoiddrawV(Graphics g) {if(!enabled) {
Sentence sen=newSentence(info.getFormattedName());intx=(width-sen.getContentWidth(g))/2;inty=(height-sen.getContentHeight(g)+Config.getConfig().getV_SPACE())/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);return;
}//首先看是不是初始化完毕了if(!initDone) {
Sentence temp=newSentence("正在搜索歌词");intx=getSentenceX(g, temp);inty=(height-temp.getContentHeight(g))/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, temp.getContent(), x, y);return;
}//如果只存在一句的话,那就不要浪费那么多计算的时候了//直接画在中间就可以了if(list.size()==1) {
Sentence sen=list.get(0);intx=getSentenceX(g, sen);inty=(height-sen.getContentHeight(g))/2;
g.setColor(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);
}else{longt=tempTime;
Graphics2D gd=(Graphics2D) g;intindex=getNowSentenceIndex(t);if(!isMoving) {
currentIndex=index;
}if(index==-1) {
Sentence sen=newSentence(info.getFormattedName(), Integer.MIN_VALUE, Integer.MAX_VALUE);intx=getSentenceX(g, sen);inty=(height-sen.getContentHeight(g))/2;
gd.setPaint(Config.getConfig().getLyricHilight());
Util.drawString(g, sen.getContent(), x, y);return;
}
Sentence now=list.get(index);//先求出中间的最基准的纵座标inty=(height+now.getContentHeight(g))/2-now.getVIncrease(g, t);intx=getSentenceX(g, now);this.drawKaraoke(gd, now, x, y, t);
gd.setColor(Config.getConfig().getLyricForeground());//然后再画上面的部份以及下面的部份//这样就可以保证正在唱的歌词永远在正中间显示inttempY=y;//画出本句之前的句子for(inti=index-1; i>=0; i--) {
Sentence sen=list.get(i);intx1=getSentenceX(g, sen);
tempY=tempY-sen.getContentHeight(g)-Config.getConfig().getV_SPACE();if(tempY+sen.getContentHeight(g)<0) {break;
}if(Config.getConfig().isLyricShadow()) {if(i==index-1) {
gd.setColor(sen.getBestOutColor(Config.getConfig().getLyricHilight(),
Config.getConfig().getLyricForeground(), time));
}else{
gd.setColor(Config.getConfig().getLyricForeground());
}
}
Util.drawString(g, sen.getContent(), x1, tempY);
}
gd.setColor(Config.getConfig().getLyricForeground());
tempY=y;//画出本句之后的句子for(inti=index+1; i
Sentence sen=list.get(i);intx1=getSentenceX(g, sen);
tempY=tempY+sen.getContentHeight(g)+Config.getConfig().getV_SPACE();if(tempY>height) {break;
}
Util.drawString(g, sen.getContent(), x1, tempY);
}
}
}/*** 得到当前正在播放的那一句的下标
* 不可能找不到,因为最开头要加一句
* 自己的句子 ,所以加了以后就不可能找不到了
*@return下标*/privateintgetNowSentenceIndex(longt) {for(inti=0; i
}
}//throw new RuntimeException("竟然出现了找不到的情况!");return-1;
}/*** 水平移动多少个象素,这个方法是给面板调用的
* 移动了这些象素以后,要马上算出这个象素所
* 对应的时间是多少,要注意时间超出的情况
*@paramlength
*@paramg 画笔,因为对于每一个画笔长度不一样的*/publicvoidmoveH(intlength, Graphics g) {if(list.size()==1||!enabled) {return;
}//如果长度是大于0的,则说明是正向移动,快进if(length>0) {
Sentence now=list.get(currentIndex);intnowWidth=now.getContentWidth(g);floatf=(time-now.getFromTime())*1.0f/(now.getToTime()-now.getFromTime());//先算出当前的这一句还剩多少长度了intrest=(int) ((1-f)*nowWidth);longtimeAdd=0;//要加多少时间//如果剩下的长度足够了,那是最好,马上就可以返回了if(rest>length) {
timeAdd=now.getTimeH(length, g);
}else{
timeAdd=now.getTimeH(rest, g);for(inti=currentIndex; i
Sentence sen=list.get(i);intlen=sen.getContentWidth(g);//如果加上下一句的长度还不够,就把时间再加,继续下一句if(len+rest
timeAdd+=sen.getDuring();
rest+=len;
}else{
timeAdd+=sen.getTimeH(length-rest, g);break;
}
}
}
tempTime=time+timeAdd;
checkTempTime();
}else{//否则就是反向移动,要快退了length=0-length;//取它的正数Sentence now=list.get(currentIndex);intnowWidth=now.getContentWidth(g);floatf=(time-now.getFromTime())*1.0f/(now.getToTime()-now.getFromTime());//先算出当前的这一句已经用了多少长度了intrest=(int) (f*nowWidth);longtimeAdd=0;//要加多少时间//如果剩下的长度足够了,那是最好,马上就可以返回了if(rest>length) {
timeAdd=now.getTimeH(length, g);
}else{
timeAdd=now.getTimeH(rest, g);for(inti=currentIndex; i>0; i--) {
Sentence sen=list.get(i);intlen=sen.getContentWidth(g);//如果加上下一句的长度还不够,就把时间再加,继续下一句if(len+rest
timeAdd+=sen.getDuring();
rest+=len;
}else{
timeAdd+=sen.getTimeH(length-rest, g);break;
}
}
}
tempTime=time-timeAdd;
checkTempTime();
}
}/*** 竖直移动多少个象素,这个方法是给面板调用的
* 移动了这些象素以后,要马上算出这个象素所
* 对应的时间是多少,要注意时间超出的情况
*@paramlength
*@paramg 画笔,因为对于每一个画笔长度不一样的*/publicvoidmoveV(intlength, Graphics g) {if(list.size()==1||!enabled) {return;
}//如果长度是大于0的,则说明是正向移动,快进if(length>0) {
Sentence now=list.get(currentIndex);intnowHeight=now.getContentHeight(g);floatf=(time-now.getFromTime())*1.0f/(now.getToTime()-now.getFromTime());//先算出当前的这一句还剩多少长度了intrest=(int) ((1-f)*nowHeight);longtimeAdd=0;//要加多少时间//如果剩下的长度足够了,那是最好,马上就可以返回了if(rest>length) {
timeAdd=now.getTimeV(length, g);
}else{
timeAdd=now.getTimeV(rest, g);for(inti=currentIndex; i
Sentence sen=list.get(i);intlen=sen.getContentHeight(g);//如果加上下一句的长度还不够,就把时间再加,继续下一句if(len+rest
timeAdd+=sen.getDuring();
rest+=len;
}else{
timeAdd+=sen.getTimeV(length-rest, g);break;
}
}
}
tempTime=time+timeAdd;
checkTempTime();
}else{//否则就是反向移动,要快退了length=0-length;//取它的正数Sentence now=list.get(currentIndex);intnowHeight=now.getContentHeight(g);floatf=(time-now.getFromTime())*1.0f/(now.getToTime()-now.getFromTime());//先算出当前的这一句已经用了多少长度了intrest=(int) (f*nowHeight);longtimeAdd=0;//要加多少时间//如果剩下的长度足够了,那是最好,马上就可以返回了if(rest>length) {
timeAdd=now.getTimeV(length, g);
}else{
timeAdd=now.getTimeV(rest, g);for(inti=currentIndex; i>0; i--) {
Sentence sen=list.get(i);intlen=sen.getContentHeight(g);//如果加上下一句的长度还不够,就把时间再加,继续下一句if(len+rest
timeAdd+=sen.getDuring();
rest+=len;
}else{
timeAdd+=sen.getTimeV(length-rest, g);break;
}
}
}
tempTime=time-timeAdd;
checkTempTime();
}
}/*** 是否能拖动,只有有歌词才可以被拖动,否则没有意义了
*@return能否拖动*/publicbooleancanMove() {returnlist.size()>1&&enabled;
}/*** 得到当前的时间,一般是由显示面板调用的*/publiclonggetTime() {returntempTime;
}/*** 在对tempTime做了改变之后,检查一下它的
* 值,看是不是在有效的范围之内*/privatevoidcheckTempTime() {if(tempTime<0) {
tempTime=0;
}elseif(tempTime>during) {
tempTime=during;
}
}/*** 告诉歌词,要开始移动了,
* 在此期间,所有对歌词的直接的时间设置都不理会*/publicvoidstartMove() {
isMoving=true;
}/*** 告诉歌词拖动完了,这个时候的时间改
* 变要理会,并做更改*/publicvoidstopMove() {
isMoving=false;
}publicstaticvoidmain(String[] args) {
}
}