編輯:關於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);
}
}
今天時間不多,沒看明白的留言吧。
一、問題描述基於百度地圖實現檢索指定城市指定公交的交通路線圖,效果如圖所示二、通用組件Application類,主要創建並初始化BMapManagerpublic cla
今天要做一個帶箭頭的圓角矩形菜單,大概長下面這個樣子: 要求頂上的箭頭要對准菜單錨點,菜單項按壓反色,菜單背景色和按壓色可配置。最簡單的做法就是讓UX給個三角形
Oracle VM VirtualBoxCentos cron計劃任務: 命令示例: Cat 1.txtTac 1.txtFin
在Android native編寫代碼時,會經常接觸到sp、wp,sp並不是smart pointer的意思,而是strong point;wp就是weak point