Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android麥克風錄音帶音量大小動態顯示的圓形自定義View

Android麥克風錄音帶音量大小動態顯示的圓形自定義View

編輯:關於Android編程

1、所謂無圖無真相,先上效果圖。我們要實現的就是中間那個錄音的按鈕,周邊會顯示一圈音量大小的波形

\

2、VolumCircleBar繼承自View,我們進行了自定義,代碼如下

<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">package com.rdinfo.ccenglish.ui.ccprofile.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; import com.panshi.xuexiao.R; /** * 麥克風音量圓形按鈕 * @author [email protected] * @version [CCEnglish, 2014-7-25] */ public class VolumCircleBar extends View { private double volumRate; // 音量百分比 private boolean isRecording; // 錄音標志 private Object lock = new Object(); private Thread uiThread; private Paint mPaint; private RectF arcRect; private Matrix matrix = new Matrix(); private final int VOLUM_INDICATE_LENGTH = 5; // 音量大小線長度 private final int CIRCLE_INNER_DISTANCE_TO_OUTSIDE = 5; // 內切圓距離外圓的距離 public VolumCircleBar(Context context) { this(context, null); } public VolumCircleBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public VolumCircleBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.VolumCircleBar, defStyle, 0); init(typedArray); } private int recordingColor; // 錄音背景色 private int stoppedColor; // 停止背景色 private Bitmap centerRes; // 中間麥克風圖片 private int totalBlockCount; // 塊數量 private int spliteAngle; // 塊之間的間隔角度大小 private int circleWidth; // 直徑 /** * 初始化 */ private void init(TypedArray typedArray) { for (int i = 0; i < typedArray.length(); i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.VolumCircleBar_recordingColor: recordingColor = typedArray.getColor(i, Color.GREEN); break; case R.styleable.VolumCircleBar_stoppedColor: stoppedColor = typedArray.getColor(i, Color.GRAY); break; case R.styleable.VolumCircleBar_centerRes: centerRes = BitmapFactory.decodeResource(getContext().getResources(), typedArray.getResourceId(i, R.drawable.ic_launcher)); break; case R.styleable.VolumCircleBar_blockCount: totalBlockCount = typedArray.getInt(i, 50); break; case R.styleable.VolumCircleBar_splitAngle: spliteAngle = typedArray.getInt(i, 2); break; } } typedArray.recycle(); uiThread = Thread.currentThread(); mPaint = new Paint(); if (spliteAngle * totalBlockCount > 360) { throw new IllegalArgumentException("spliteAngle * blockCount > 360, while the result should be less than 360."); } // debug for test isRecording = true; volumRate = 0.5; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 直徑 int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); circleWidth = width > height? width : height; if (arcRect == null) { arcRect = new RectF(CIRCLE_INNER_DISTANCE_TO_OUTSIDE, CIRCLE_INNER_DISTANCE_TO_OUTSIDE, circleWidth - CIRCLE_INNER_DISTANCE_TO_OUTSIDE, circleWidth - CIRCLE_INNER_DISTANCE_TO_OUTSIDE); // 音量顯示區域, 內偏移幾個像素 // 圖片處理矩陣 initBitmapMatrix(); } // 強制設置view大小 setMeasuredDimension(circleWidth, circleWidth); } /** * 中間圖片壓縮處理 */ private void initBitmapMatrix() { float innerCircleRadius = (circleWidth - 2 * (VOLUM_INDICATE_LENGTH + CIRCLE_INNER_DISTANCE_TO_OUTSIDE)) / 2f; // 內圓的半徑 float innerRectangleWidth = (float)Math.cos((Math.PI / 180) * 45) * innerCircleRadius * 2; // 內圓的內切正方形的邊長 float translateOffset = VOLUM_INDICATE_LENGTH + CIRCLE_INNER_DISTANCE_TO_OUTSIDE + innerCircleRadius - innerRectangleWidth / 2; // 偏移的offset if (centerRes.getWidth() > (innerRectangleWidth) || centerRes.getHeight() > (innerRectangleWidth)) { // 圖片寬度或高度大於(直徑-內偏移), 等比壓縮 if (centerRes.getWidth() > centerRes.getHeight()) { // 按照寬度壓縮 float ratio = innerRectangleWidth / centerRes.getWidth(); matrix.postScale(ratio, ratio); float translateY = (innerRectangleWidth - (centerRes.getHeight() * ratio)) / 2f; // 在縱坐標方向上進行偏移,以保證圖片居中顯示 matrix.postTranslate(translateOffset, translateY + translateOffset); } else { // 按照高度壓縮 float ratio = innerRectangleWidth / (centerRes.getHeight() * 1.0f); matrix.postScale(ratio, ratio); float translateX = (innerRectangleWidth - (centerRes.getWidth() * ratio)) / 2f; // 在橫坐標方向上進行偏移,以保證圖片居中顯示 matrix.postTranslate(translateX + translateOffset, translateOffset); } } else { // 當圖片的寬高都小於屏幕寬高時,直接讓圖片居中顯示 float translateX = (innerRectangleWidth - centerRes.getWidth()) / 2f; float translateY = (innerRectangleWidth - centerRes.getHeight()) / 2f; matrix.postTranslate(translateX + translateOffset, translateY + translateOffset); } } /** * 設置音量百分比 * @param rate */ public void updateVolumRate(double rate) { synchronized (lock) { this.volumRate = rate; if (Thread.currentThread() != uiThread) { postInvalidate(); } else { invalidate(); } } } /** * 開始、停止錄音 */ public void toggleRecord() { synchronized (lock) { isRecording = !isRecording; if (Thread.currentThread() != uiThread) { postInvalidate(); } else { invalidate(); } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.TRANSPARENT); synchronized (lock) { if (isRecording) // 正在錄音 { //1.繪制綠色圓圈 mPaint.setAntiAlias(true); //消除鋸齒 mPaint.setColor(recordingColor); mPaint.setStrokeWidth(1); mPaint.setStyle(Paint.Style.FILL); // 填充 canvas.drawCircle(circleWidth / 2f, circleWidth / 2f, circleWidth / 2f, mPaint); //2.根據音量百分比、塊數量、塊間隔大小計算角度動態繪制音量大小 // 計算塊的角度 float blockAngle = (360 * 1.0f - spliteAngle * totalBlockCount) / totalBlockCount; int drawBlockCount = (int)(totalBlockCount * volumRate); // 繪制的block數量 mPaint.setStrokeWidth(VOLUM_INDICATE_LENGTH); mPaint.setColor(stoppedColor); mPaint.setStyle(Paint.Style.STROKE); // 空心 for (int i = 0; i < drawBlockCount; i++) { canvas.drawArc(arcRect, i * (blockAngle + spliteAngle) - 90, blockAngle, false, mPaint); } } else // 錄音停止 { //1.繪制灰色圓圈 mPaint.setColor(stoppedColor); mPaint.setStrokeWidth(1); mPaint.setStyle(Paint.Style.FILL); // 填充 canvas.drawCircle(circleWidth / 2f, circleWidth / 2f, circleWidth / 2f, mPaint); } } // 繪制中間話筒 canvas.drawBitmap(centerRes, matrix, null); } }
今天時間不多,沒看明白的留言吧。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved