歌词同步的简单处理
MainActivity.java
public class MainActivity extends Activity { /** * 装歌词的集合 */ private ArrayList<String> lrcList; /** * 装每行歌词的集合 */ private ArrayList<Lyric> singleList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 判断SD卡存不存在 String state = Environment.getExternalStorageState(); if (!Environment.MEDIA_MOUNTED.equals(state)){ Toast.makeText(this, "内存卡移除,请插入!", 0).show(); return; } lrcList = new ArrayList<String>(); lrcList=getLrctoString();//得到歌词 singleList=new ArrayList<Lyric>(); parserLrc();//解析歌词到singleList MyView myView=(MyView) findViewById(R.id.myView); for (Lyric l : singleList) { if(l.getLrcString()==null){ l.setLrcString(""); } } myView.init(singleList); MediaPlayer mp = MediaPlayer.create(MainActivity.this, R.raw.a);//播放当前工程文件里的音频 sound_file_1为音频文件 mp.start(); } /** * 切割歌词 */ private Lyric spiltString(String current){ Lyric lrc=new Lyric(); if(current.contains(":")&¤t.contains(".")){ String[] split = current.split("]"); if(split.length==2){ lrc.setLrcString(split[1]);//设置歌词 }else{ lrc.setLrcString("");//设置歌词为空 } timeTransform(lrc,split[0].substring(1)); } return lrc; } /** * 时间换算 得到显示的时间与维持的时间 * @param lrc 一行的对象 * @param substring 00:00.27 的格式 分钟:秒钟.毫秒 */ private void timeTransform(Lyric lrc, String substring) { String[] split = substring.trim().split(":"); int minute=Integer.parseInt(split[0]);//分 String[] spl = split[1].split("\\."); int second=Integer.parseInt(spl[0]);//秒 int ms=Integer.parseInt(spl[1]);//毫秒 lrc.setStartTime((minute*60+second)*1000+ms*10);//设置开始的毫秒数 } /** * 解析歌词 */ private void parserLrc(){ for (int i = 0; i < lrcList.size(); i++) { Lyric lyric = spiltString(lrcList.get(i)); if(lyric!=null){ singleList.add(lyric);//还差维持时间 } } //将维持时间设置上 for (int i = 0; i < singleList.size()-1; i++) { int sleepTime=singleList.get(i+1).getStartTime()-singleList.get(i).getStartTime(); singleList.get(i).setSleepTime(sleepTime); } } /** * 返回歌词 */ private ArrayList<String> getLrctoString(){ try { // 获得SD卡的存储目录 File path = Environment.getExternalStorageDirectory(); // 获得手机内部存储目录 //File dataFileDir = Environment.getDataDirectory(); File file=new File(path+"//Music//老鼠爱大米.lrc"); BufferedReader br=new BufferedReader(new FileReader(file)); String line; ArrayList<String> list=new ArrayList<String>(); while((line=br.readLine())!=null){ list.add(line); } return list; } catch (IOException e) { e.printStackTrace(); } return null; } }
MyView.java
public class MyView extends TextView { private ArrayList<Lyric> singleList;//歌词 private int currentLine = 0;//当前行 private int lineSpacing = 120; //行间距 //当前正在播放的行 private Paint currentPaint; private int currentColor = Color.YELLOW;//颜色 private int currentSize = 55;//字体大小 private Typeface currentTypeface = Typeface.DEFAULT_BOLD;//字体,默认的字体+粗体 //其他行 private Paint ortherPaint; private int ortherColor = Color.BLACK; private int ortherSize = 40; private Typeface ortherTypeface = Typeface.SERIF;//一种字体类型 private Handler handler = new Handler() { public void handleMessage(Message msg) { currentLine++;//行数自加 invalidate(); } }; public MyView(Context context, AttributeSet attrs) { super(context, attrs); } /** * 绘制内容 */ @Override protected void onDraw(Canvas canvas) { if (singleList != null ) {// 避免程序一运行就执行该方法 if(currentLine<=singleList.size()){ for (int i = 0; i < singleList.size(); i++) { Lyric lyric = singleList.get(i); if (i == currentLine) {// 当前行,应该显示在正中间 canvas.drawText(lyric.getLrcString(), getWidth()/2, getHeight()/2, currentPaint);// 以屏幕正中间为起源 } else {// 当前行的其他内容 ortherPaint.setAlpha(225-Math.abs((i - currentLine)*30));//设置透明度 canvas.drawText(lyric.getLrcString(), getWidth()/2, getHeight()/2 + (i - currentLine) * lineSpacing,//行距,以屏幕中心为参考设置行距 ortherPaint); } } if(currentLine<singleList.size()){ //延时当前行维持的时间后发送消息 handler.sendEmptyMessageDelayed(1, singleList.get(currentLine).getSleepTime()); } } } } /** * 初始化 */ public void init(ArrayList<Lyric> singleList){ this.singleList = singleList; currentPaint = new Paint();//当前行 currentPaint.setColor(currentColor); currentPaint.setAntiAlias(true);//打开抗锯齿 currentPaint.setTextSize(currentSize); currentPaint.setTextAlign(Align.CENTER);//文字居中对齐 currentPaint.setTypeface(currentTypeface);//设置字体 ortherPaint = new Paint();//其他行 ortherPaint.setColor(ortherColor); ortherPaint.setAntiAlias(true); ortherPaint.setTextSize(ortherSize); ortherPaint.setTextAlign(Align.CENTER); ortherPaint.setTypeface(ortherTypeface); invalidate();//更新内容,调用onDraw方法 } /** * 还是没有跑马灯效果 */ @Override public boolean isFocused() { return true; } }
歌词封装类:Lyric.java
/** * 歌词类 */ public class Lyric { /** * 开始时间 */ private int startTime; /** * 改行歌词占用时间 */ private int sleepTime; /** * 一行的歌词 */ private String lrcString; public int getStartTime() { return startTime; } public void setStartTime(int startTime) { this.startTime = startTime; } public int getSleepTime() { return sleepTime; } public void setSleepTime(int sleepTime) { this.sleepTime = sleepTime; } public String getLrcString() { return lrcString; } public void setLrcString(String lrcString) { this.lrcString = lrcString; } public Lyric(int startTime, int sleepTime, String lrcString) { super(); this.startTime = startTime; this.sleepTime = sleepTime; this.lrcString = lrcString; } public Lyric() { super(); } @Override public String toString() { return "startTime=" + startTime + ", sleepTime=" + sleepTime + ", lrcString=" + lrcString; } }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <!-- 没有跑马灯效果 --> <com.example.mymusic.MyView android:background="#ccccff" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/myView"/> </RelativeLayout>
效果图: