music player:一(歌词显示,LyricView,Canvas)---自动滚动

Blogfor明月依希 2010-08-18

    

      网上androi播放器虽然挺多,感觉提供的歌词显示功能比较死板,要么搜索给的条件死死的,要么放置sdcard内部的歌词格式需要统一,应该提供类似文件夹浏览的功能。^_^,不过在这之前先搞定歌词的现实界面:

      转载请注明http://ishelf.iteye.com/admin/blogs/740402

      播放器的歌词界面实现以下几个功能

  1. 根据歌曲的播放进度自下而上滚动;
  2. 提供上下拖动调整歌曲进度的功能;
  3. 突出显示当前进度的歌词段,并保证该歌词段处于布局中心

     不多说了直接贴代码,首先开启一个线程每隔一段时间往view中送入一串字符

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class TextAlign extends GraphicsActivity implements OnClickListener {

	private SampleView mView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Animation in = AnimationUtils.loadAnimation(this, R.anim.push_up_in);

		// mView.setAnimation(in);
		setContentView(R.layout.main);
		mView =(SampleView) findViewById(R.id.text01);

		Button bt = (Button) findViewById(R.id.Button01);
		bt.setOnClickListener(this);
		
		new Thread(new UIUpdateThread()).start();

	}

	class UIUpdateThread implements Runnable {
		long time = 40000;

		long sleeptime = 100;
		public void run() {
			try {
				while (time < 200000) {
					Thread.sleep(sleeptime);
					mView.updateIndex(time);//.index = mLyric.getNowSentenceIndex(time);
//					Log.v("UIThread", mView.index + ":" + time);
					time += sleeptime;
					mHandler.post(mUpdateResults);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	Handler mHandler = new Handler();
	Runnable mUpdateResults = new Runnable() {
		public void run() {
			mView.invalidate(); // 更新视图
		}
	};

	@Override
	public void onClick(View v) {
		mView.mTouchHistoryY -=30;
		mHandler.post(mUpdateResults);
	}
}

     这里将时间送到SampleView中,该类对此时间进行加工得到一系列list(该list是动态生成的),从而根据时间的推移递增的得到一系列的字串。这个过程模拟了歌词的显示过程

      接下来的SampleView继承了TextView并重载了onDraw方法.注意,这里只给了个sample,里面歌词怎么生成的见YOYOPlayer。这里就不给代码了

import java.io.File;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
import android.widget.Toast;

import com.android.lyric.Lyric;
import com.android.lyric.PlayListItem;
import com.android.lyric.Sentence;

public class SampleView extends TextView {
		private Paint mPaint;
		private float mX;
		private static Lyric mLyric;

		private Path mPath;
		private Paint mPathPaint;
		public String test = "test";
		public int index = 0;
		private List<Sentence> list;

		private float mTouchStartY;
		private float mTouchCurrY;
		public float mTouchHistoryY;

		private int mY;
		private long currentTime;
		private long currentDunringTime;
		private long sentenctTime;
		private float middleY;
		private String middleContent="Empty";
		private static final int DY = 30;

		private static void makePath(Path p) {
			p.moveTo(10, 0);
			p.cubicTo(100, -50, 200, 50, 300, 0);
		}


		public SampleView(Context context) {
			super(context);
			init();
		}
		public SampleView(Context context,AttributeSet attr) {
			super(context,attr);
			init();
		}
		public SampleView(Context context,AttributeSet attr,int i) {
			super(context,attr,i);
			init();
		}

		private void init() {
			setFocusable(true);
			PlayListItem pli = new PlayListItem("", "", 1000L, true);
			mLyric = new Lyric(new File("/sdcard/M0005044007.lrc"), pli);

			list = mLyric.list;
			mPaint = new Paint();
			mPaint.setAntiAlias(true);
			mPaint.setTextSize(20);
			mPaint.setTypeface(Typeface.SERIF);


			mPath = new Path();
			makePath(mPath);

			mPathPaint = new Paint();
			mPathPaint.setAntiAlias(true);
			mPathPaint.setColor(0x800000FF);
			mPathPaint.setStyle(Paint.Style.STROKE);
		}

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

			canvas.drawColor(Color.WHITE);

			Paint p = mPaint;
			float x = mX;
			float plus =currentDunringTime==0?index*30: index*30 +(((float)currentTime - (float)sentenctTime)/(float)currentDunringTime)*(float)30;
			float y =  mY- plus+mTouchCurrY - mTouchStartY+mTouchHistoryY;
				
			canvas.translate(0,y);

			for (int i = 0; i < index; i++) {
				String text = list.get(i).getContent();
				if((y+i*30)<=middleY&&(y+i*30+30)>=middleY)
					middleContent = text;
				p.setTextAlign(Paint.Align.CENTER);
				canvas.drawText(text, x, 0, p);
				// mY- mY/lines*(index - i)
				canvas.translate(0, DY);
			}
		}


		@Override
		protected void onSizeChanged(int w, int h, int ow, int oh) {
			super.onSizeChanged(w, h, ow, oh);
			mX = w * 0.5f; // remember the center of the screen
			mY = h;
			middleY = h*0.5f;
		}

		@Override
		public boolean onTouchEvent(MotionEvent event) {
			float y = event.getY();

			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
				mTouchHistoryY += mTouchCurrY - mTouchStartY;
				mTouchStartY =mTouchCurrY= y;
				invalidate();
				break;
			case MotionEvent.ACTION_MOVE:
				mTouchCurrY = y;
				invalidate();
				break;
			case MotionEvent.ACTION_UP:
				Log.v("Lyric content", middleContent.length()+"");
				CharSequence chars = new  CharSequence(){

					@Override
					public char charAt(int index) {
						// TODO Auto-generated method stub
						return middleContent.charAt(index);
					}

					@Override
					public int length() {
						// TODO Auto-generated method stub
						return middleContent.length();
					}

					@Override
					public CharSequence subSequence(int start, int end) {
						// TODO Auto-generated method stub
						return middleContent.subSequence(start, end);
					}
					@Override
					public String toString(){
						return middleContent;
					}
				};
				Toast toast = Toast.makeText(SampleView.this.getContext(),chars, 1000);
				toast.show();
				invalidate();
				break;
			}
			return true;
		}


		public void updateIndex(long time) {
			this.currentTime = time;
			index = mLyric.getNowSentenceIndex(time);
			Sentence sen = list.get(index);
			currentDunringTime = sen.getDuring();
			sentenctTime  = sen.getFromTime();
		}
	}

相关推荐