package com.wk.unittestshow;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.util.AttributeSet;import android.view.View;import android.view.ViewTreeObserver;import androidx.annotation.NonNull;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.ArrayList;import java.util.List;/*** 声音波形的view <br>* 波形能左右移动的原理: <br>* 将自定义控件分成 listMaxSize 份,每份对应一个分贝值 ,* 根据分贝值的大小 来决定 线条的高度。* 分贝值更新引起ui更新,所以会形成从左向右效果。* mRecDataList.add(dbValue) ;* mRecDataList.remove(0) ;*/public class AudioWaveView extends View {private Bitmap mBackgroundBitmap;private Canvas mBackCanVans = new Canvas();/**波浪的画笔*/private Paint mPaint;/**绘制最终画面的 画笔*/private Paint mViewPaint;private final ArrayList<Integer> mRecDataList = new ArrayList<>();private int mScale = 1;/**控件总长度*/private int viewWidth;/**高度中间线 ,作为基准线*/private int mBaseLine;/**波形之间线与线的间隔*/private int smaleLineWidth = 0;/**一共画多少个小线条*/int listMaxSize = 0 ;/**是否画出基线*/private boolean mDrawBase = true;private boolean mPause = false;/**1 只画上面的波纹 ,2、上下都画*/private int mWaveCount = 2;private Context context ;public AudioWaveView(Context context) {super(context);init(context, null);}public AudioWaveView(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public AudioWaveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if (mBackgroundBitmap != null && !mBackgroundBitmap.isRecycled()) {mBackgroundBitmap.recycle();}}public void init(Context context, AttributeSet attrs) {// 防止因为xml可视化失败导致编译错误if (isInEditMode()){return;}this.context = context ;mPaint = new Paint();mPaint.setColor(Color.parseColor("#00ff33"));mViewPaint = new Paint();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);creatBackGroundBitmap();}@Overrideprotected void onVisibilityChanged(@NonNull View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);if (visibility == VISIBLE && mBackgroundBitmap == null) {creatBackGroundBitmap();}}private void creatBackGroundBitmap() {ViewTreeObserver vto = getViewTreeObserver();vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {if (getWidth() > 0 && getHeight() > 0) {smaleLineWidth = WkDeviceInforTool.getPixByDp( context ,2) ;listMaxSize = getWidth() / smaleLineWidth ;viewWidth = getWidth();mBaseLine = getHeight() / 2;mBackgroundBitmap = Bitmap.createBitmap( getWidth(), getHeight(), Bitmap.Config.ARGB_8888);mBackCanVans.setBitmap(mBackgroundBitmap);mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);ViewTreeObserver vto = getViewTreeObserver();// 移除绘制回调函数vto.removeOnPreDrawListener(this);}return true;}});}private void updateDrawParam(){ArrayList<Integer> dataList = new ArrayList<>();synchronized (mRecDataList) {if (mRecDataList.size() != 0) {try {dataList = (ArrayList<Integer>) deepCopy(mRecDataList);} catch (Exception e) {e.printStackTrace();}}}if (!mPause) {// 获得最新缩放参数updateScale(dataList);if (mBackCanVans != null) {// 清除画布mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);// 绘制基准线if (mDrawBase) {mBackCanVans.drawLine(0, mBaseLine, viewWidth, mBaseLine, mPaint);}//绘制小线条形成波浪int dbSize = dataList.size();for (int i = 0, j = 0; i < dbSize; i++, j += smaleLineWidth) {int dbValue = dataList.get(i);drawDbLine(dbValue, j);}// 通知 重绘postInvalidate();}}}@Overrideprotected void onDraw(Canvas c) {super.onDraw(c);if ( mBackgroundBitmap != null) {c.drawBitmap(mBackgroundBitmap, 0, 0, mViewPaint);}}/**** 根据当前分贝值对应的一小段 线条*/private void drawDbLine(int dbValue, int smaleLineWidth) {int max = mBaseLine - dbValue / mScale;if (mWaveCount == 2) {int min= mBaseLine + dbValue / mScale;mBackCanVans.drawLine(smaleLineWidth, mBaseLine, smaleLineWidth, max, mPaint);mBackCanVans.drawLine(smaleLineWidth, mBaseLine , smaleLineWidth,min , mPaint);} else {mBackCanVans.drawLine(smaleLineWidth, mBaseLine, smaleLineWidth, max, mPaint);}}/*** deepClone* @param src list* @return dest*/public List deepCopy(ArrayList src) throws IOException, ClassNotFoundException {ByteArrayOutputStream byteOut = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(byteOut);out.writeObject(src);ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());ObjectInputStream in = new ObjectInputStream(byteIn);return (ArrayList) in.readObject();}/*** 根据当前块数据 更新 缩放音频显示的比例*/private void updateScale(ArrayList<Integer> list) {int allMax = 0;for (int i = 0; i < list.size(); i++) {int sh = list.get(i);if ( sh > allMax) {allMax = sh;}}int curScale = allMax / mBaseLine;if (curScale > mScale) {mScale = curScale == 0 ? 1 : curScale ;}}/*** 停止绘制*/public void stopView( ) {mRecDataList.clear();mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);}public void updateDataList(int dbValue ){if(mRecDataList.size() > listMaxSize){mRecDataList.add(dbValue) ;mRecDataList.remove(0) ;}else{mRecDataList.add(dbValue) ;}updateDrawParam();}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。