`
ishelf
  • 浏览: 106334 次
  • 性别: 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内容太多,能不能只把该部分的完整代码贴出来,谢谢

相关推荐

    Leaflet.Canvas-Markers-0.2.0

    本文将深入探讨Leaflet.Canvas-Markers-0.2.0,一个专门为Leaflet设计的插件,用于在地图上高效地绘制Canvas标记。 Leaflet.Canvas-Markers是Leaflet的一个扩展,它引入了一种新的标记类型,即使用HTML5 Canvas元素...

    vue-canvas-poster 海报合成

    在这个“vue-canvas-poster”项目中,我们将探讨如何结合Vue和Canvas来实现一个海报合成的功能。 首先,Vue组件是Vue.js的核心概念,它允许开发者将UI拆分成可复用的部分。在这个案例中,“vue-canvas-poster”可能...

    wxa-comp-canvas-drag-master.zip

    微信小程序canvas-drag组件是为了解决在微信小程序中对图片进行编辑的需求而设计的。这个组件基于canvas元素,提供了一种简单的方式让用户在小程序内部实现图片的拉伸、压缩和裁剪操作。通过这个组件,开发者可以...

    Python库 | orange-canvas-core-0.1.0b2.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:orange-canvas-core-0.1.0b2.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    Python库 | streamlit_drawable_canvas-0.5.1-py3-none-any.whl

    资源分类:Python库 所属语言:Python 资源全名:streamlit_drawable_canvas-0.5.1-py3-none-any.whl 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    html2canvas-1.0.0-rc.4版本

    html2canvas-1.0.0-rc.4版本

    JavaScript-Canvas-to-Blob-master

    如果目标浏览器不支持原生的`toBlob`方法,JavaScript-Canvas-to-Blob-master将自动处理这个过程,保证在所有现代浏览器及部分旧版浏览器中的兼容性。这极大地扩展了开发者在跨平台Web应用中使用Canvas的能力,尤其...

    JavaScript-Canvas-to-Blob:JavaScript Canvas to Blob是将画布元素转换为Blob对象的功能

    这会将JavaScript文件相对于当前目录安装在./node_modules/blueimp-canvas-to-blob/js/ ,您可以从中将它们复制到Web服务器提供的文件夹中。 接下来,在HTML标记中包含缩小JavaScript Canvas to Blob脚本: &lt; ...

    canvas-basic-graphics.zip

    `canvas-basic-graphics.zip`中的代码实例就是一个很好的起点,帮助开发者理解并实践`canvas`的基本图形绘制。通过学习和实践,开发者能够进一步掌握`canvas`的高级特性,如渐变、阴影、路径动画等,从而在网页设计...

    ec-canvas 实现echart图表显示

    ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-canvas 实现echart图表显示ec-...

    使用新版canvas-2d接口在微信小程序中生成二维码(外部二维码)的js包

    使用新版canvas-2d接口在微信小程序中生成二维码(外部二维码)的js包

    canvas-keyframes.min.js添加序列帧动画

    canvas-keyframes.min.js添加序列帧动画,动态添加,无论是横版序列图还是竖版序列图

    Python库 | Oasys-Canvas-Core-1.0.3.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:Oasys-Canvas-Core-1.0.3.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    vue-sign-canvas-master.zip

    Vue-sign-canvas-master.zip是一个包含Vue.js组件的压缩包,专为实现电子签名功能而设计。这个组件基于HTML5的canvas元素,使得用户能够在PC和移动设备上进行手写签名,适用于各种需要签名确认的场景,如电子商务、...

    转载:酷炫背景------瀑布流

    在这个“html5-canvas-waterfall-lake”压缩包中,很可能包含了一个使用HTML5 Canvas元素来模拟动态瀑布效果的示例。 Canvas是HTML5的一个重要特性,它允许开发者在网页上进行图形绘制,通过JavaScript API可以实现...

    react-canvas-dom:Canvas组件和reactjs的钩子

    npm: npm i react-canvas-dom 纱线: yarn add react-canvas-dom 导入组件并使用它: Import Canvas from 'react-canvas-dom' const draw = ( ctx , i ) =&gt; { ctx . clearRect ( 0 , 0 , ctx . canvas . width ...

    前端项目-javascript-canvas-to-blob.zip

    这个“前端项目-javascript-canvas-to-blob.zip”包含了一个示例项目,帮助开发者理解并应用这一功能。 该项目的核心在于`canvas.toBlob()`方法。这个方法接收一个回调函数作为参数,当转换完成时,会将生成的Blob...

    canvas-nest-react.js

    见http://blog.csdn.net/carllucasyu/article/details/79022775

    jest-canvas-mock:用于在Jest中模拟画布的模块

    npm i --save-dev jest-canvas-mock设置在jest下的package.json ,创建一个setupFiles数组,然后将jest-canvas-mock添加到该数组中。 { " jest " : { " setupFiles " : [ " jest-canvas-mock " ] }} 如果已经具有...

    node-canvas-webgl:node-canvas 和 headless-gl 的集成

    节点画布-webgl 和集成。演示:与三个js const fs = require ( 'fs' ) ;const THREE = require ( 'three' ) ;const GIFEncoder = require ( 'gifencoder' ) ;...const canvas = createCanvas ( width , height ) ;con

Global site tag (gtag.js) - Google Analytics