Android 音乐播放器实现歌词显示

时间:2022-08-10 10:17:59

LrcHandle.java:

package com.example.welcome;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/***
 * 获取时间以及对应的歌词
 * 
 * @author chao
 * 
 */
public class LrcHandle {
	private List<String> mWords = new ArrayList<String>();
	private List<Integer> mTimeList = new ArrayList<Integer>();

	// 处理歌词文件
	public void readLRC(String path) {
		File file = new File(path);

		try {
			FileInputStream fileInputStream = new FileInputStream(file);
			InputStreamReader inputStreamReader = new InputStreamReader(
					fileInputStream, "GBK");
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);
			String s = "";
			while ((s = bufferedReader.readLine()) != null) {
				addTimeToList(s);
				if ((s.indexOf("[ar:") != -1) || (s.indexOf("[ti:") != -1)
						|| (s.indexOf("[by:") != -1)) {
					s = s.substring(s.indexOf(":") + 1, s.indexOf("]"));
				} else {
					// ss为时间 [02:12.22]
					String ss = s.substring(s.indexOf("["), s.indexOf("]") + 1);
					// s为ss时间后的歌词
					s = s.replace(ss, "");
				}
				mWords.add(s);
			}

			bufferedReader.close();
			inputStreamReader.close();
			fileInputStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			mWords.add("没有歌词文件,赶紧去下载");
		} catch (IOException e) {
			e.printStackTrace();
			mWords.add("没有读取到歌词");
		}
	}

	public List<String> getWords() {
		return mWords;
	}

	public List<Integer> getTime() {
		return mTimeList;
	}

	// 分离出时间
	private int timeHandler(String string) {
		string = string.replace(".", ":");
		String timeData[] = string.split(":");
		// 分离出分、秒并转换为整型
		int minute = Integer.parseInt(timeData[0]);
		int second = Integer.parseInt(timeData[1]);
		int millisecond = Integer.parseInt(timeData[2]);

		// 计算上一行与下一行的时间转换为毫秒数
		int currentTime = (minute * 60 + second) * 1000 + millisecond * 10;

		return currentTime;
	}

	private void addTimeToList(String string) {
		Matcher matcher = Pattern.compile(
				"\\[\\d{1,2}:\\d{1,2}([\\.:]\\d{1,2})?\\]").matcher(string);
		if (matcher.find()) {
			String str = matcher.group();
			mTimeList.add(new LrcHandle().timeHandler(str.substring(1,
					str.length() - 1)));
		}
	}
}
WordView.java:

package com.example.welcome;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;

public class WordView extends TextView {
	private List mWordsList = new ArrayList();
	private Paint mLoseFocusPaint;
	private Paint mOnFocusePaint;
	private float mX = 0;
	private float mMiddleY = 0;
	private float mY = 0;
	private static final int DY = 50;
	private int mIndex = 0;

	public WordView(Context context) throws IOException {
		super(context);
		init();
	}

	public WordView(Context context, AttributeSet attrs) throws IOException {
		super(context, attrs);
		init();
	}

	public WordView(Context context, AttributeSet attrs, int defStyle)
			throws IOException {
		super(context, attrs, defStyle);
		init();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		canvas.drawColor(Color.BLACK);
		Paint p = mLoseFocusPaint;
		p.setTextAlign(Paint.Align.CENTER);
		Paint p2 = mOnFocusePaint;
		p2.setTextAlign(Paint.Align.CENTER);

		canvas.drawText((String) mWordsList.get(mIndex), mX, mMiddleY, p2);

		int alphaValue = 25;
		float tempY = mMiddleY;
		for (int i = mIndex - 1; i >= 0; i--) {
			tempY -= DY;
			if (tempY < 0) {
				break;
			}
			p.setColor(Color.argb(255 - alphaValue, 245, 245, 245));
			canvas.drawText((String) mWordsList.get(i), mX, tempY, p);
			alphaValue += 25;
		}
		alphaValue = 25;
		tempY = mMiddleY;
		for (int i = mIndex + 1, len = mWordsList.size(); i < len; i++) {
			tempY += DY;
			if (tempY > mY) {
				break;
			}
			p.setColor(Color.argb(255 - alphaValue, 245, 245, 245));
			canvas.drawText((String) mWordsList.get(i), mX, tempY, p);
			alphaValue += 25;
		}
		mIndex++;
	}

	@Override
	protected void onSizeChanged(int w, int h, int ow, int oh) {
		super.onSizeChanged(w, h, ow, oh);

		mX = w * 0.5f;
		mY = h;
		mMiddleY = h * 0.3f;
	}

	@SuppressLint("SdCardPath")
	private void init() throws IOException {
		setFocusable(true);

		LrcHandle lrcHandler = new LrcHandle();
		lrcHandler.readLRC("/sdcard/aa.lrc");
		mWordsList = lrcHandler.getWords();

		mLoseFocusPaint = new Paint();
		mLoseFocusPaint.setAntiAlias(true);
		mLoseFocusPaint.setTextSize(22);
		mLoseFocusPaint.setColor(Color.WHITE);
		mLoseFocusPaint.setTypeface(Typeface.MONOSPACE);

		mOnFocusePaint = new Paint();
		mOnFocusePaint.setAntiAlias(true);
		mOnFocusePaint.setColor(Color.YELLOW);
		mOnFocusePaint.setTextSize(40);
		mOnFocusePaint.setTypeface(Typeface.SANS_SERIF);
	}
}
MainActivity.java:

package com.example.welcome;

import java.io.IOException;
import java.util.List;

import android.R.integer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
	private WordView mWordView;
	private List mTimeList;
	private MediaPlayer mPlayer;

	@SuppressLint("SdCardPath")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Button button = (Button) findViewById(R.id.button);
		button.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				mPlayer.stop();
				finish();
			}
		});

		mWordView = (WordView) findViewById(R.id.text);
		mPlayer = new MediaPlayer();
		mPlayer.reset();
		LrcHandle lrcHandler = new LrcHandle();
		try {
			lrcHandler.readLRC("/sdcard/aa.lrc");
			mTimeList = lrcHandler.getTime();
			mPlayer.setDataSource("/sdcard/e.mp3");
			mPlayer.prepare();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		}
		final Handler handler = new Handler();
		mPlayer.start();
		new Thread(new Runnable() {
			int i = 0;

			@Override
			public void run() {
				while (mPlayer.isPlaying()) {
					handler.post(new Runnable() {
						@Override
						public void run() {
							mWordView.invalidate();
						}
					});
					try {
						Thread.sleep(Integer.parseInt(mTimeList.get(i + 1)
								.toString())
								- Integer.parseInt(mTimeList.get(i).toString()));
					} catch (InterruptedException e) {
					}
					i++;
					if (i == mTimeList.size() - 1) {
						mPlayer.stop();
						break;
					}
				}
			}
		}).start();
	}
}
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" >

    <Button
        android:id="@+id/button"
        android:layout_width="60dip"
        android:layout_height="60dip"
        android:text="stop" />

    <com.example.welcome.WordView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/button"
        android:text="song" />

</RelativeLayout>