实现歌词同步源码
- - ITeye博客利用TextView实现歌词同步显示,这是一个简单的利用TextView实现滚动实时显示歌词的. 里面的内容都已经写上了详细的注释. 里面播放音乐的时候歌词同步展示. 做媒体这块的朋友可以学习一下,练练歌词同步实现方法. 歌词实现展示类TextShow,. 项目源码来源: http://www.itlanbao.com/code/20151214/10000/100695.html.
实现歌词同步
介绍:
利用TextView实现歌词同步显示,这是一个简单的利用TextView实现滚动实时显示歌词的。
里面的内容都已经写上了详细的注释。里面播放音乐的时候歌词同步展示。
做媒体这块的朋友可以学习一下,练练歌词同步实现方法。
歌词实现展示类TextShow,
项目源码来源: http://www.itlanbao.com/code/20151214/10000/100695.html
效果截图:
主要代码如下:
package com.example.textviewchange; import java.io.BufferedReader; import java.io.FileDescriptor; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.widget.TextView; public class MainActivity extends Activity { private MediaPlayer player; private TextView tv; private boolean flag=false;//用来停止和判断线程 private int i; private TextShow ts; private Map<String,String> map,map1; private int count=5; private List<String> list; private String s=""; private boolean change=false; Looper looper=Looper.getMainLooper(); Handler handler=new Handler(looper){ public void handleMessage(android.os.Message msg) { if(msg.what==10&&flag==false){ if(i==map1.size()){//判断歌词是不是已经全部显示 flag=true; //如果销毁了activity则,不执行下面的方法 return; } Changetext(); } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.tv); //获取assert中的歌曲文件以及歌词文件 AssetManager am=getAssets(); AssetFileDescriptor afd; //使用媒体播放器 player=new MediaPlayer(); //设置播放的音频类型 player.setAudioStreamType(AudioManager.STREAM_MUSIC); try { afd = am.openFd("apple.mp3"); FileDescriptor fd=afd.getFileDescriptor(); player.setDataSource(fd); //获取sd卡中的歌曲文件 //player.setDataSource("/sdcard/Music/apple.mp3"); player.prepare(); } catch (IOException e1) { e1.printStackTrace(); } //开始播放 player.start(); //测试,这里应该用输入输出流读取文件 map1=new HashMap<>(); list=new ArrayList<>(); //加载歌词文件 read(); //保留插入顺序 //设置给显示界面刚开始显示5行 map=new LinkedHashMap<String,String>(); for(int i=0;i<5;i++){ map.put(list.get(i), map1.get(list.get(i))); } ts=new TextShow(map); new Thread(){ public void run() { while(!flag){ try { sleep(500); Message mes=new Message(); mes.what=10; handler.sendMessage(mes); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } public void Changetext(){ //给正在播放的歌词添加样式 if(map!=null&&map.get(conTime(player.getCurrentPosition()))!=null){ String s1=""; tv.setText(ts.Add(conTime(player.getCurrentPosition()).toString())); s1=conTime(player.getCurrentPosition()).toString(); //判断在相同的时间段内,Changetext方法是不是执行了两次 if(!s.equals(s1)){ change=true; s=s1; }else{ change=false; } if(change){ //设置正在播放的歌词的上方的行数 if(i>5){ //移除最顶部的一行 map.remove(list.get(i-6)); } //增加一行在最底部 if(count<map1.size()){ map.put(list.get(count), map1.get(list.get(count))); } i++; count++; } } } //读取LRC的歌词文件 public void read(){ try { InputStream in=getAssets().open("c.lrc"); BufferedReader bf=new BufferedReader(new InputStreamReader(in)); String msg=""; while((msg=bf.readLine())!=null){ if(msg.length()!=0){ //保存歌词的时间以及歌词内容 map1.put(msg.substring(1,6), msg.substring(msg.lastIndexOf("]")+1)+"\n"); //保存每一行歌词的时间 list.add(msg.substring(1,6)); } } bf.close(); } catch (IOException e) { e.printStackTrace(); } } @Override protected void onDestroy() { super.onDestroy(); if(player!=null){ player.stop(); player.release(); player=null; } flag=true; } //将音频的播放时间转换成00:00的格式 public CharSequence conTime(int duration) { int second=duration/1000; int miunte=second/60; second=second%60; String miunte1 = String.valueOf(miunte); String second1 = String.valueOf(second); if(miunte<10){ miunte1="0"+miunte; }if(second<10){ second1="0"+second; } return miunte1+":"+second1; } }
特殊文字显示 (歌词同步显示)
package com.example.textviewchange; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import android.graphics.Color; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.AbsoluteSizeSpan; import android.text.style.ForegroundColorSpan; /* * 特殊文字显示 (歌词同步显示) * */ public class TextShow { private SpannableStringBuilder ssb; private SpannableString ss; //private String str; private Map<String,String> map; //传入的map必须为LinkedHashMap public TextShow(Map<String,String> map) { this.map=map; ssb=new SpannableStringBuilder(); } //设置字符串的样式(如果要分行显示,在传入的字符串中添加"\n") //根据字符串从map中取值 public SpannableString changeText(String str){ ss=new SpannableString(str); //设置字符串的大小 ss.setSpan(new AbsoluteSizeSpan(50),0,ss.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //设置字符串的颜色 ss.setSpan(new ForegroundColorSpan(Color.MAGENTA), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return ss; } //追加到SpannableStringBuilder中某一行 //ss 需要追加的有样式的字符串 public SpannableStringBuilder Add(String str){ //清除上一次的数据 ssb.clear(); //遍历map Iterator<Entry<String, String>> iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String,String> entry = (Map.Entry<String,String>) iter.next(); String key = entry.getKey(); String val = entry.getValue(); if(key.equals(str)){ ssb.append(changeText(val)); } else{ SpannableString ss1=new SpannableString(val); ssb.append(ss1); } } /* 也可以用下面的方法 * for(String string:map.values()){ if(string.equals(map.get(str))){ ssb.append(changeText(str)); }else{ SpannableString ss1=new SpannableString(string); ssb.append(ss1); } }*/ return ssb; } }