chenjinlong 2012-04-24
我们要实现一个类似于小米分享中的圆形播放进度条,android自带的圆形ProgressBar是默认自动旋转的,所以无法实现,于是我们想到了使用自定义一个View,来实现这种效果。
首先来看看自己定义的View
packagecn.easymobi.application.bell.common;
importandroid.content.Context;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Paint;
importandroid.graphics.RectF;
importandroid.util.AttributeSet;
importandroid.view.View;
publicclassProgressViewextendsView{
privatefloatfArcNum;
privatefloatfMax;
privatefloatdensity;
publicfloatgetDensity(){
returndensity;
}
publicvoidsetDensity(floatdensity){
this.density=density;
}
publicProgressView(Contextcontext){
super(context);
}
publicProgressView(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
protectedvoidonDraw(Canvascanvas){
//TODOAuto-generatedmethodstub
super.onDraw(canvas);
Paintpaint=newPaint();
if(fArcNum>0)
{
paint.setColor(Color.GRAY);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
canvas.drawCircle(40*density/2,40*density/2,40*density/2,paint);}
paint.setColor(Color.YELLOW);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
//paint.setStrokeWidth(2);
RectFrect=newRectF(0,0,40*density,40*density);
canvas.drawArc(rect,-90,fArcNum,true,paint);
paint.setColor(Color.BLACK);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
canvas.drawCircle(40*density/2,40*density/2,40*density/2-5,paint);
}
publicvoidsetProgress(floatnum)
{
fArcNum = (num/fMax) * 360;this.postInvalidate();
}
publicfloatgetfArcNum(){
returnfArcNum;
}
publicvoidsetfArcNum(floatfArcNum){
this.fArcNum=fArcNum;
}
publicfloatgetfMax(){
returnfMax;
}
publicvoidsetfMax(floatfMax){
this.fMax=fMax;
}
}使用:
private ProgressView progress; float num=0; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.clean); progress=(ProgressView)findViewById(R.id.progress_main_clean); progress.setDensity(1); progress.setfMax(100); Timer timer=new Timer(); MyTask task=new MyTask(); timer.schedule(task,0, 500); } class MyTask extends TimerTask{ @Override public void run() { // TODO Auto-generated method stub progress.setProgress(num); System.out.println("number"+num); num++; } }
我们通过重写View的onDraw方法,根据fArcNum好fMax来判断当前播放到的位置,然后不停的刷新改View就实现了这个效果。至于画弧,是采用了drawArc方法,然后通过在其内部画圆遮盖多余部分实现。
下面是MediaPlayer与该View的同步处理,核心代码如下
//*******************************************************************
//Func:playAudio
//
//by:Sun
//2011.9.1
//*******************************************************************
publicvoidplayAudio(finalStringpath,finalProgressBarpb){
Threadthread=newThread(newRunnable(){
publicvoidrun(){
try{
if(mpMediaPlayer!=null){
mpMediaPlayer.stop();
mpMediaPlayer.release();
mpMediaPlayer=null;
}
mpMediaPlayer=newMediaPlayer();
mpMediaPlayer.setDataSource(path);
mpMediaPlayer.prepare();
mpMediaPlayer
.setOnPreparedListener(newOnPreparedListener(){
publicvoidonPrepared(MediaPlayermp){
pb.setVisibility(ProgressBar.GONE);
frontPv.setfMax(mpMediaPlayer.getDuration());
frontPv.setProgress(0);
mpMediaPlayer.start();
refrash=newThread(newRunnable(){
publicvoidrun(){
try{
while(frontPv.getfArcNum()<=360
&&mpMediaPlayer
.isPlaying()){
if(bIsOver)
break;
frontPv.setProgress(mpMediaPlayer
.getCurrentPosition());
Thread.sleep(1000);
mHandle.sendEmptyMessage(MSG_REFRESH_UI);
}
mHandle.sendEmptyMessage(MSG_PLAY_OVER);
}catch(Exceptione){
e.printStackTrace();
}
}
});
refrash.start();
}
});
}catch(Exceptione){
e.printStackTrace();
}
}
});
thread.start();
}
其中frontPv是我们自己定义的view,最后发送handler是调用invalidate方法刷新该view,mpMediaPlayers是我们定义的MediaPlayer对象。我们通过在进程中每隔一秒更新frontPv当中的fArcNum并且刷新实现转动的动画效果。
原文章出处 http://labs.ywlx.net/?p=1296