`
ishelf
  • 浏览: 105337 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

阅读更多

    

      网上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();
		}
	}
9
3
分享到:
评论
9 楼 ysc123shift 2017-11-08  
给的东西,稍微欠完整。对于初学者,参考意义不大。
8 楼 sunny09290 2013-10-21  
楼主,请问当歌词太长,需要换行该怎么处理呢
7 楼 zhongyuanceshi 2013-02-01  
博主,GraphicsActivity这个类是你自己写的吧,TextAlign继承它,没有看到实现了它的什么函数功能。GraphicsActivity是干嘛用的?这样你的代码不能用亚
6 楼 j086924 2011-07-30  
我是初学者,感觉难以理解!
5 楼 ishelf 2011-04-19  
ishelf 写道
piaozhiye 写道
突出显示当前进度的歌词段,并保证该歌词段处于布局中心 。这个怎么实现呢?

在播放歌曲的同时,可以使用一个线程进行歌词同步。  每个时间段都对应一句歌词,你只要将这句歌词至中就可以了,具体代码你可以参考mTouchHistoryY,mTouchStartY这几个值的设置,以及在onDraw方法里面的使用( float y =  mY- plus+mTouchCurrY - mTouchStartY+mTouchHistoryY )

   补充一点,就是建议你先写个小Demo实现以下通过歌词控制歌曲播放的功能和通过歌曲控制歌词显示的功能
4 楼 ishelf 2011-04-19  
piaozhiye 写道
突出显示当前进度的歌词段,并保证该歌词段处于布局中心 。这个怎么实现呢?

在播放歌曲的同时,可以使用一个线程进行歌词同步。  每个时间段都对应一句歌词,你只要将这句歌词至中就可以了,具体代码你可以参考mTouchHistoryY,mTouchStartY这几个值的设置,以及在onDraw方法里面的使用( float y =  mY- plus+mTouchCurrY - mTouchStartY+mTouchHistoryY )
3 楼 piaozhiye 2011-04-12  
突出显示当前进度的歌词段,并保证该歌词段处于布局中心 。这个怎么实现呢?
2 楼 piaozhiye 2011-04-11  
supercw 写道
感觉比较有用,但是YOYOplayer内容太多,能不能只把该部分的完整代码贴出来,谢谢

1 楼 supercw 2010-09-23  
感觉比较有用,但是YOYOplayer内容太多,能不能只把该部分的完整代码贴出来,谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics