注:本文是《android群英传》3.6.3.2节 音频条形图的学习笔记。大部分内容参考书籍,加上个人的一些理解。
最终的效果如下:
分析:这样的一个音频条形图,怎么样实现呢?
大体思路:绘制一个个矩形,每一个矩形之间,偏移一点距离即可
- 难点在于坐标的设置(其实也不难)
- 基础知识:坐标原点在左上角。音频图底部高度是不需要改变的,即y坐标固定
- y轴方向
- 在OnSizeChange中使用了getHeight获取View的高度,赋值给rectHeight
- 每一个柱的高度使用random 产生的值去乘以 rectHeight即可
- x轴方向(逐渐往右偏移)
- 从左到右,自view的宽度的 20% 处开始,按照柱的宽度和偏移量递增
- 柱宽度设置为 View宽的0.6倍除以柱子数目 (mWidth * 0.6 / mRectCount)
- 从左到右,自view的宽度的 20% 处开始,按照柱的宽度和偏移量递增
- y轴方向
具体实现代码
public class VolumeView extends View {
private int mWidth;//View宽度
private int mRectWidth;//音量柱宽
private int mRectHeight;//音量柱高
private Paint mPaint;
private int offset = 5;//柱与柱之间的间隔
private int mRectCount;//音量柱数目
private double mRandom;
private LinearGradient mLinearGradient;//线性渲染
public VolumeView(Context context) {
super(context);
initView();
}
public VolumeView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.FILL);
mRectCount = 12;
}
//当view尺寸改变时,获取view的一些属性,进行一些初始化操作
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = getWidth();//获取view的宽度
mRectHeight = getHeight();//获取view的高度
mRectWidth = (int) (mWidth * 0.6 / mRectCount);
mLinearGradient = new LinearGradient(0, 0, mRectWidth, mRectHeight, Color.YELLOW, Color.BLUE, Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < mRectCount; i++) {
mRandom = Math.random();
float currentHeight = (float) (mRectHeight * mRandom);//随机生成音量柱的左上方的y坐标
canvas.drawRect(
(float) (mWidth * 0.4 / 2 + mRectWidth * i + offset),
currentHeight,
(float) (mWidth * 0.4 / 2 + mRectWidth * (i + 1) ),
mRectHeight,
mPaint);
}
//每隔300ms通知view进行重绘(如果每次一会绘制完就通知重绘刷新太快效果不太好)
postInvalidateDelayed(300);
}
}
实际应用需要根据音频输入去修改currentHeight;