国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android自定義View實(shí)現(xiàn)音頻播放圓形進(jìn)度條

2019-10-21 21:49:02
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

本篇文章介紹自定義View配合屬性動(dòng)畫(huà)來(lái)實(shí)現(xiàn)如下的效果

Android,View,音頻播放,進(jìn)度條

實(shí)現(xiàn)思路如下:

  • 根據(jù)播放按鈕的圖片大小計(jì)算出圓形進(jìn)度條的大小
  • 根據(jù)音頻的時(shí)間長(zhǎng)度計(jì)算出圓形進(jìn)度條繪制的弧度
  • 通過(guò)Handler刷新界面來(lái)更新圓形進(jìn)度條的進(jìn)度

具體實(shí)現(xiàn)過(guò)程分析:

首先來(lái)看看自定義View中定義的一些成員變量

 //表示坐標(biāo)系中的一塊矩形區(qū)域  private RectF mRectF;  //畫(huà)筆  private Paint mPaint;  //畫(huà)筆寬度  private int mCircleStoreWidth = 3;  //最大進(jìn)度值  private int mMaxProcessValue = 100;  //進(jìn)度值  private int mProcessValue;  private int width;  private int height;  //播放器按鈕id值  private int bitmapPlay;  private int bitmapStop;  //播放器按鈕Bitmap對(duì)象  private Bitmap drawBitmapPlay;  private Bitmap drawBitmapStop;  private Context context;  //標(biāo)記是否正在播放中  private boolean isPlay;

初始化自定義View,在這里獲取播放器按鈕圖片以及初始化畫(huà)布畫(huà)筆對(duì)象以及設(shè)置將畫(huà)筆設(shè)置抗鋸齒

private void init(Context context, AttributeSet attrs, int defStyleAttr) {    this.context = context;    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.circle_progress_image_attrs);    bitmapPlay = a.getResourceId(R.styleable.circle_progress_image_attrs_play_image, R.mipmap.play_button);    bitmapStop = a.getResourceId(R.styleable.circle_progress_image_attrs_stop_image, R.mipmap.stop_button);    a.recycle();    drawBitmapPlay = BitmapFactory.decodeResource(context.getResources(), bitmapPlay);    drawBitmapStop = BitmapFactory.decodeResource(context.getResources(), bitmapStop);    mRectF = new RectF();    mPaint = new Paint();    mPaint.setAntiAlias(true);  }

這里使用了自定義attrs來(lái)獲取播放器按鈕圖片 

在attrs.xml中新建如下:

<declare-styleable name="circle_progress_image_attrs">    <attr name="play_image" format="reference"/>    <attr name="stop_image" format="reference"/>  </declare-styleable>

然后在xml布局的自定義View中加入就能獲取圖片的id值了

 circle:play_image="@mipmap/play_button" circle:stop_image="@mipmap/stop_button"

然后我們重寫(xiě)onMeasure()來(lái)測(cè)量圓形進(jìn)度條繪制的位置

@Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    width = measureWidth(widthMeasureSpec);    height = measureWidth(heightMeasureSpec);    mRectF.left = width / 2 - drawBitmapPlay.getWidth() / 2;    mRectF.top = height / 2 - drawBitmapPlay.getHeight() / 2;    mRectF.right = width / 2 + drawBitmapPlay.getWidth() / 2;    mRectF.bottom = height / 2 + drawBitmapPlay.getHeight() / 2;  }  public int measureWidth(int measureSpec) {    int result = 0;    int specMode = MeasureSpec.getMode(measureSpec);    int specSize = MeasureSpec.getSize(measureSpec);    if (specMode == MeasureSpec.EXACTLY) {      result = specSize;    } else {      result = 200;      if (specMode == MeasureSpec.AT_MOST) {        result = Math.min(specSize, result);      }    }    return result;  }

獲取播放器按鈕圖片的大小后,計(jì)算出進(jìn)度條的相應(yīng)的坐標(biāo)放入RectF對(duì)象中,RectF對(duì)象是用來(lái)表示坐標(biāo)系中的一塊矩形區(qū)域,用于在特定的位置畫(huà)圖

然后我們就可以通過(guò)重寫(xiě)onDraw()方法來(lái)繪制View了

@Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    canvas.drawColor(Color.TRANSPARENT);    //畫(huà)圓    mPaint.setColor(ContextCompat.getColor(context, R.color.orange));    mPaint.setStyle(Paint.Style.STROKE);    mPaint.setStrokeWidth(mCircleStoreWidth);    //    canvas.drawArc(mRectF, -90, 360, false, mPaint);    mPaint.setColor(ContextCompat.getColor(context, R.color.gray));    canvas.drawArc(mRectF, -90, ((float) mProcessValue / mMaxProcessValue) * 360, false, mPaint);    Log.d(TAG, ((float) mProcessValue / mMaxProcessValue) * 360 + "");    float imageLeft = width / 2 - drawBitmapPlay.getWidth() / 2;    float imageTop = height / 2 - drawBitmapPlay.getHeight() / 2;    if (isPlay) {      canvas.drawBitmap(drawBitmapStop, imageLeft, imageTop, mPaint);    } else {      canvas.drawBitmap(drawBitmapPlay, imageLeft, imageTop, mPaint);    }  }

要點(diǎn)其實(shí)就是canvas.drawArc()方法在RecfF的位置里畫(huà)弧形,通過(guò)音頻播放的開(kāi)始時(shí)間/總時(shí)間*360來(lái)計(jì)算出弧度 
要注意的是每次調(diào)用onDraw()方法的時(shí)候都需要先將canvas畫(huà)透明色來(lái)起到清屏的作用

通過(guò)handler來(lái)每150毫秒刷新一次界面

private Handler handler = new Handler() {    public void handleMessage(Message msg) {      switch (msg.what) {        case 1:          //定時(shí)更新界面          if (isPlay) {            mProcessValue += 150;            if (mProcessValue == mMaxProcessValue) {              isPlay = false;            }            invalidate();            Message message = handler.obtainMessage(1);            handler.sendMessageDelayed(message, 150);          }      }      super.handleMessage(msg);    }  };

最后是一些包裝方法,很簡(jiǎn)單不仔細(xì)介紹了

public void play() {    isPlay = true;    Message message = handler.obtainMessage(1);    handler.sendMessageDelayed(message, 150);  }  public void setDuration(int duration) {    this.mMaxProcessValue = duration;  }  public void clearDuration() {    this.mMaxProcessValue = 0;    this.mProcessValue = 0;  }  public void pause() {    isPlay = false;    invalidate();  }  public void stop() {    isPlay = false;    this.mMaxProcessValue = 0;    this.mProcessValue = 0;    invalidate();  }

音頻播放的邏輯實(shí)現(xiàn)部分因?yàn)椴粚儆谧远xview因此可以自行參考demo

代碼示例: CustomViewSamples

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 渝北区| 嘉善县| 白银市| 德江县| 台东市| 珠海市| 江津市| 奈曼旗| 新和县| 大理市| 新和县| 江孜县| 奉化市| 财经| 兴化市| 新邵县| 庆元县| 阿瓦提县| 额敏县| 瑞金市| 石景山区| 霸州市| 青铜峡市| 尼木县| 共和县| 突泉县| 星子县| 永福县| 中西区| 桓台县| 双鸭山市| 迭部县| 兴城市| 光泽县| 义乌市| 陇西县| 湖州市| 项城市| 毕节市| 长寿区| 阳春市|