Android编程实现类似于圆形ProgressBar的进度条效果

作者:袖梨 2022-06-25

我们要实现一个类似于小米分享中的圆形播放进度条,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(Context context) {

    super(context);

  }

  publicProgressView(Context context,AttributeSet attrs) {

    super(context,attrs);

  }

  protectedvoidonDraw(Canvas canvas) {

    // TODO Auto-generated method stub

    super.onDraw(canvas);

    Paint paint=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);

    RectF rect=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;

  }

  publicfloatgetfArcNum() {

    returnfArcNum;

  }

  publicvoidsetfArcNum(floatfArcNum) {

    this.fArcNum = fArcNum;

  }

  publicfloatgetfMax() {

    returnfMax;

  }

  publicvoidsetfMax(floatfMax) {

    this.fMax = fMax;

  }

}

 

我们通过重写View的onDraw方法,根据fArcNum好fMax来判断当前播放到的位置,然后不停的刷新改View就实现了这个效果。至于画弧,是采用了drawArc方法,然后通过在其内部画圆遮盖多余部分实现。

下面是MediaPlayer与该View的同步处理,核心代码如下

 

 代码如下复制代码

// *******************************************************************

// Func: playAudio

//

// by: Sun

// 2011.9.1

// *******************************************************************

publicvoidplayAudio(finalString path,finalProgressBar pb) {

  Thread thread =newThread(newRunnable() {

    publicvoidrun() {

      try{

        if(mpMediaPlayer !=null) {

          mpMediaPlayer.stop();

          mpMediaPlayer.release();

          mpMediaPlayer =null;

        }

        mpMediaPlayer =newMediaPlayer();

        mpMediaPlayer.setDataSource(path);

        mpMediaPlayer.prepare();

        mpMediaPlayer.setOnPreparedListener(newOnPreparedListener() {

          publicvoidonPrepared(MediaPlayer mp) {

            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(Exception e) {

                  e.printStackTrace();

                }

              }

            });

            refrash.start();

          }

        });

      }

      catch(Exception e) {

        e.printStackTrace();

      }

    }

  });

  thread.start();

}

 

其中frontPv是我们自己定义的view,最后发送handler是调用invalidate方法刷新该  view,mpMediaPlayers是我们定义的MediaPlayer对象。我们通过在进程中每隔一秒更新frontPv当中的fArcNum并且  刷新实现转动的动画效果。

相关文章

精彩推荐