####绘制矩形抖动
我们要绘制音频抖动的效果,矩形的高度肯定不能一样,而是要根据声音的大小来显示,这里我们没有声音,简单模拟一下给高度乘上for循环里的i效果如图:
至此我们已经知道了如何绘制多个矩形,并控制不同的高度,那我们要如何动态的控制高度呢?比如我们点击开始录音的时候,就会动态的传入声音的大小,这个分贝值控制着矩形的抖动。要实现这个动态的效果,我们需要不断的设置分贝,并不断的刷新。所以我们可以开启一个线程,不断设置音量的分贝,并不断的刷新。为了让矩形抖动有错落感,就需要让每个矩形抖动的值不一样,所以我们设置一个list存储音量值,并依次改变里面的值即可。
private static final int MIN_WAVE_HEIGHT = 2;//矩形线最小高
private static final int MAX_WAVE_HEIGHT = 12;//矩形线最大高
private static final int[] DEFAULT_WAVE_HEIGHT = {2, 2, 2, 2};
private static final int UPDATE_INTERVAL_TIME = 100;//100ms更新一次
private LinkedList mWaveList = new LinkedList<>();
private float maxDb;
private void resetView(List list, int[] array) {
list.clear();
for (int anArray : array) {
list.add(anArray);
}
}
private synchronized void refreshElement() {
Random random = new Random();
maxDb = random.nextInt(5) + 2;
int waveH = MIN_WAVE_HEIGHT + Math.round(maxDb * (MAX_WAVE_HEIGHT - MIN_WAVE_HEIGHT));
mWaveList.add(0, waveH);
mWaveList.removeLast();
}
public boolean isStart = false;
private class LineJitterTask implements Runnable {
@Override
public void run() {
while (isStart) {
refreshElement();
try {
Thread.sleep(updateSpeed);
} catch (Exception e) {
e.printStackTrace();
}
postInvalidate();
}
}
}
public synchronized void startRecord() {
isStart = true;
executorService.execute(task);
}
public synchronized void stopRecord() {
isStart = false;
mWaveList.clear();
resetView(mWaveList, DEFAULT_WAVE_HEIGHT);
postInvalidate();
}
1.为了控制矩形抖动的范围,我们需要设置一个最大值和最小值。
2.并利用数组设置矩形的默认值,因为有四个矩形,所以数组大小为4
3.定义一个分贝值,控制矩形的高度
4.重置View的时候把默认的数组传进去,就可以达到View的重置,比如View的初始化,和停止录音的时候
5.刷新元素方法,用于不停的刷新矩阵的高度,让矩阵抖起来。这里用随机数模拟声音大小,传给数组,每次都添加到第一个,然后每次都移除最后一个,这样能让矩阵按顺序抖动。
6.在线程中调用这个刷新矩阵的方法,当开始录音的时候,在while中刷新矩阵,并睡眠100ms,这样就实现了没100ms刷新一次view,开始录音的时候设置isStart为true。
7.在停止录音的时候设置isStart为false,并初始化矩形为原始高度。由于在线程中刷新View,应该使用postInvalidate()方法。
至此这个逻辑已经实现了,稍微润色一下即可实现录音时的音频抖动
效果如图:
完整代码:
/**
- 语音录制的动画效果
*/
public class LineWaveVoiceView extends View {
private static final String DEFAULT_TEXT = " 请录音 ";
private static final int LINE_WIDTH = 9;//默认矩形波纹的宽度,9像素, 原则上从layout的attr获得
private Paint paint = new Paint();
private Runnable task;
private ExecutorService executorService = Executors.newCachedThreadPool();
private RectF rectRight = new RectF();//右边波纹矩形的数据,10个矩形复用一个rectF
private RectF rectLeft = new RectF();//左边波纹矩形的数据
private String text = DEFAULT_TEXT;
private int updateSpeed;
private int lineColor;
private int textColor;
private float lineWidth;
private float textSize;
public LineWaveVoiceView(Context context) {
super(context);
}
public LineWaveVoiceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LineWaveVoiceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs, context);
resetView(mWaveList, DEFAULT_WAVE_HEIGHT);
task = new LineJitterTask();
}
private void initView(AttributeSet attrs, Context context) {
//获取布局属性里的值
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.LineWaveVoiceView);
lineColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceLineColor, context.getColor(R.color.defaultLineColor));
lineWidth = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceLineWidth, LINE_WIDTH);
textSize = mTypedArray.getDimension(R.styleable.LineWaveVoiceView_voiceTextSize, 42);
textColor = mTypedArray.getColor(R.styleable.LineWaveVoiceView_voiceTextColor, context.getColor(R.color.defaultTextColor));
updateSpeed = mTypedArray.getColor(R.styleable.LineWaveVoiceView_updateSpeed, UPDATE_INTERVAL_TIME);
mTypedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取实际宽高的一半
int widthCentre = getWidth() / 2;
int heightCentre = getHeight() / 2;
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(textSize);
float textWidth = paint.measureText(text);
canvas.drawText(text, widthCentre - textWidth / 2, heightCentre - (paint.ascent() + paint.descent()) / 2, paint);
//设置颜色
paint.setColor(lineColor);
//填充内部
paint.setStyle(Paint.Style.FILL);
//设置抗锯齿
paint.setAntiAlias(true);
for (int i = 0; i < 10; i++) {
rectRight.left = widthCentre + textWidth / 2 + (1 + 2 * i) * lineWidth;
rectRight.top = heightCentre - lineWidth * mWaveList.get(i) / 2;
rectRight.right = widthCentre + textWidth / 2 + (2 + 2 * i) * lineWidth;
rectRight.bottom = heightCentre + lineWidth * mWaveList.get(i) / 2;
//左边矩形
rectLeft.left = widthCentre - textWidth / 2 - (2 + 2 * i) * lineWidth;
rectLeft.top = heightCentre - mWaveList.get(i) * lineWidth / 2;
rectLeft.right = widthCentre - textWidth / 2 - (1 + 2 * i) * lineWidth;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后
我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
《Android高级架构师面试指导+2021大厂面试真题》免费领取文章来源:https://www.toymoban.com/news/detail-857927.html
[外链图片转存中…(img-IfcqTDPI-1710828589258)]
《Android高级架构师面试指导+2021大厂面试真题》免费领取
[外链图片转存中…(img-bcyhFmgl-1710828589259)]文章来源地址https://www.toymoban.com/news/detail-857927.html
到了这里,关于Android进阶系列:八、自定义View之音频抖动动效的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!