SoFunction
Updated on 2025-03-02

Android implements the specific idea of ​​synchronous display of lyrics when playing songs


import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class LyricView extends View{
private static TreeMap<Integer, LyricObject> lrc_map;
private float mX; //The midpoint of the screen X-axis, this value is fixed, keeping the lyrics displayed in the middle of X
private float offsetY; //The offset of the lyrics on the Y axis, this value will decrease according to the lyrics' scrolling
private static boolean blLrc=false;
private float touchY; // When touching the lyrics View, save as the Y-axis coordinates of the current contact
private float touchX;
private boolean blScrollView=false;
private int lrcIndex=0; //Save the subscript of the lyrics TreeMap
private int SIZEWORD=0;//Show the size value of the lyrics text
private int INTERVAL=45;//The interval of lyrics per line
Paint paint=new Paint();// Paint brush, used to draw lyrics that are not highlighted
Paint paintHL=new Paint(); // Paint brush, used to draw highlighted lyrics, that is, the lyrics that are currently sung
public LyricView(Context context){
super(context);
init();
}
public LyricView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/* (non-Javadoc)
* @see #onDraw()
*/
@Override
protected void onDraw(Canvas canvas) {
if(blLrc){
(SIZEWORD);
(SIZEWORD);
LyricObject temp=lrc_map.get(lrcIndex);
(, mX, offsetY+(SIZEWORD+INTERVAL)*lrcIndex, paintHL);
// Lyrics before drawing the current lyrics
for(int i=lrcIndex-1;i>=0;i--){
temp=lrc_map.get(i);
if(offsetY+(SIZEWORD+INTERVAL)*i<0){
break;
}
(, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
}
// Lyrics after drawing the current lyrics
for(int i=lrcIndex+1;i<lrc_map.size();i++){
temp=lrc_map.get(i);
if(offsetY+(SIZEWORD+INTERVAL)*i>600){
break;
}
(, mX, offsetY+(SIZEWORD+INTERVAL)*i, paint);
}
}
else{
(25);
("Lyrics not found", mX, 310, paint);
}
(canvas);
}
/* (non-Javadoc)
* @see #onTouchEvent()
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
("bllll==="+blScrollView);
float tt=();
if(!blLrc){
//return (event);
return (event);
}
switch(()){
case MotionEvent.ACTION_DOWN:
touchX=();
break;
case MotionEvent.ACTION_MOVE:
touchY=tt-touchY;
offsetY=offsetY+touchY;
break;
case MotionEvent.ACTION_UP:
blScrollView=false;
break;
}
touchY=tt;
return true;
}
public void init(){
lrc_map = new TreeMap<Integer, LyricObject>();
offsetY=320;
paint=new Paint();
();
();
(true);
(true);
(180);
paintHL=new Paint();
();
();
(true);
(255);
}
/**
* Determine the size of the lyrics based on the longest sentence in the lyrics
*/
public void SetTextSize(){
if(!blLrc){
return;
}
int max=lrc_map.get(0).();
for(int i=1;i<lrc_map.size();i++){
LyricObject lrcStrLength=lrc_map.get(i);
if(max<()){
max=();
}
}
SIZEWORD=320/max;
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mX = w * 0.5f;
(w, h, oldw, oldh);
}
/**
* The speed of lyrics scrolling
*
* @return Return to the lyrics scrolling speed
*/
public Float SpeedLrc(){
float speed=0;
if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex>220){
speed=((offsetY+(SIZEWORD+INTERVAL)*lrcIndex-220)/20);
} else if(offsetY+(SIZEWORD+INTERVAL)*lrcIndex < 120){
("speed", "speed is too fast!!!");
speed = 0;
}
// if(speed<0.2){
// speed=0.2f;
// }
return speed;
}
/**
* According to the current playback time of the song, get the sentence from the lyrics
* @param time The current song playback time
* @return Return the index value of the current lyrics
*/
public int SelectIndex(int time){
if(!blLrc){
return 0;
}
int index=0;
for(int i=0;i<lrc_map.size();i++){
LyricObject temp=lrc_map.get(i);
if(<time){
++index;
}
}
lrcIndex=index-1;
if(lrcIndex<0){
lrcIndex=0;
}
return lrcIndex;
}
/**
* Read lyrics file
* @param file lyrics path
*
*/
public static void read(String file) {
TreeMap<Integer, LyricObject> lrc_read =new TreeMap<Integer, LyricObject>();
String data = "";
try {
File saveFile=new File(file);
// ("Is there a lyric file" +());
if(!()){
blLrc=false;
return;
}
blLrc=true;
//("bllrc==="+blLrc);
FileInputStream stream = new FileInputStream(saveFile);// (file);
BufferedReader br = new BufferedReader(new InputStreamReader(stream,"GB2312"));
int i = 0;
Pattern pattern = ("\\d{2}");
while ((data = ()) != null) {
// ("++++++++++++>>"+data);
data = ("[","");//Replace the previous one with the next one
data = ("]","@");
String splitdata[] =("@");//Separate
if(("@")){
for(int k=0;k<;k++){
String str=splitdata[k];
str = (":",".");
str = (".","@");
String timedata[] =("@");
Matcher matcher = (timedata[0]);
if(==3 && ()){
int m = (timedata[0]); //min
int s = (timedata[1]); //sec
int ms = (timedata[2]); //ms
int currTime = (m*60+s)*1000+ms*10;
LyricObject item1= new LyricObject();
= currTime;
= "";
lrc_read.put(currTime,item1);
}
}
}
else{
String lrcContenet = splitdata[-1];
for (int j=0;j<-1;j++)
{
String tmpstr = splitdata[j];
tmpstr = (":",".");
tmpstr = (".","@");
String timedata[] =("@");
Matcher matcher = (timedata[0]);
if(==3 && ()){
int m = (timedata[0]); //min
int s = (timedata[1]); //sec
int ms = (timedata[2]); //ms
int currTime = (m*60+s)*1000+ms*10;
LyricObject item1= new LyricObject();
= currTime;
= lrcContenet;
lrc_read.put(currTime,item1);// Insert currTime as label item1 as data into TreeMap
i++;
}
}
}
}
();
}
catch (FileNotFoundException e) {
}
catch (IOException e) {
}
/*
* traversal hashmap calculates the time it takes for each lyric
*/
lrc_map.clear();
data ="";
Iterator<Integer> iterator = lrc_read.keySet().iterator();
LyricObject oldval = null;
int i =0;
while(()) {
Object ob =();
LyricObject val = (LyricObject)lrc_read.get(ob);
if (oldval==null)
oldval = val;
else
{
LyricObject item1= new LyricObject();
item1 = oldval;
= ;
lrc_map.put(new Integer(i), item1);
i++;
oldval = val;
}
if (!()) {
lrc_map.put(new Integer(i), val);
}
}
}
/**
* @return the blLrc
*/
public static boolean isBlLrc() {
return blLrc;
}
/**
* @return the offsetY
*/
public float getOffsetY() {
return offsetY;
}
/**
* @param offsetY the offsetY to set
*/
public void setOffsetY(float offsetY) {
= offsetY;
}
/**
* @return Return the size of the lyrics text
*/
public int getSIZEWORD() {
return SIZEWORD;
}
/**
* Set the size of the lyrics text
* @param sIZEWORD the sIZEWORD to set
*/
public void setSIZEWORD(int sIZEWORD) {
SIZEWORD = sIZEWORD;
}
}