写点什么

Android 自定义控件 (神级)+MediaRecoder 录音,android 开发基础应用

用户头像
Android架构
关注
发布于: 刚刚

private double rad(double deg) {return deg / 180 * Math.PI;}}



3.正弦函数的动起来

什么影响正弦函数的横向位移--相位:φ

那还等什么,ValueAnimator 走起,从 0~2 * Math.PI



//数字时间流 mAnimator = ValueAnimator.ofFloat(0, (float) (2 * Math.PI));mAnimator.setDuration(1000);mAnimator.setRepeatMode(ValueAnimator.RESTART);mAnimator.setInterpolator(new LinearInterpolator());mAnimator.addUpdateListener(a -> {φ = (float) a.getAnimatedValue();invalidate();});


就这么简单?---是的



4.让凸起的部分渐渐平息

不就是对 A 值进行渐变嘛...非常简单



mAnimator.addUpdateListener(a -> {φ = (float) a.getAnimatedValue();A = (float) (mMaxHeight* (1 - (float) a.getAnimatedValue() / (2 * Math.PI)));invalidate();});



二、加入衰减函数与渐变色

1.加入衰减函数

虽然有那么点感觉,但是还是差很多,关键在对应法则,说起来也简单

但是操作起来挺费劲,衰减函数凑了好一会...



/**


  • 对应法则

  • @param x 原像(自变量)

  • @return 像(因变量)*/private double f(double x) {double len = max - min;double a = 4 / (4 + Math.pow(rad(x / Math.PI * 800 / len), 4));double aa = Math.pow(a, 2.5);ω = 2 * Math.PI / (rad(len) / 2);double y = aa * A * Math.sin(ω * rad(x) - φ);return y;}



2.加渐变色

什么颜色好呢,好吧,我计较懒,搭条彩虹吧(以前实现过)



int[] colors = new int[]{Color.parseColor("#F60C0C"),//红 Color.parseColor("#F3B913"),//橙 Color.parseColor("#E7F716"),//黄 Color.parseColor("#3DF30B"),//绿 Color.parseColor("#0DF6EF"),//青 Color.parseColor("#0829FB"),//蓝 Color.parseColor("#B709F4"),//紫};float[] pos = new float[]{1.f / 7, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 6.f / 7, 1};mPaint.setShader(new LinearGradient((int) min, 0, (int) max, 0,colors, pos,Shader.TileMode.CLAMP));



三、第二条曲线的绘制

1.路径的形成

会了一个,另一个 Y 镜像一下就行了(y 坐标边-y)


private void formPath() {mPath.moveTo((float) min, (float) f(min));mReflexPath.moveTo((float) min, (float) f(min));for (double x = min; x <= max; x++) {double y = f(x);mPath.lineTo((float) x, (float) y);mReflexPath.lineTo((float) x, -(float) y);}}



2.绘制第二条曲线:onDraw

第二条淡一点


mPaint.setAlpha(255);canvas.drawPath(mPath, mPaint);mPaint.setAlpha(66);canvas.drawPath(mReflexPath, mPaint);



3.高度设置

我的用意是在录音是监听音量大小,然后让图象波动

暴漏设置高度的方法,在设置时执行动画,下面是点击设置随机高度效果



/**


  • 设置高度

  • @param maxHeight*/public void setMaxHeight(double maxHeight) {mMaxHeight = maxHeight;mAnimator.start();invalidate();}




四、扫尾--封装


该 dp 的 dp,该删的删,该封装的封装,该优化的优化,直接贴代码


/**


  • 作者:张风捷特烈<br/>

  • 时间:2018/11/16 0016:9:04<br/>

  • 邮箱:1981462002@qq.com<br/>

  • 说明:贝塞尔三次曲线--旋律视图*/public class RhythmView extends View {private double mMaxHeight = 0;//最到点 private double mPerHeight = 0;//最到点


private double min;//最小 xprivate double max;//最大 x


private double φ = 0;//初相 private double A = mMaxHeight;//振幅 private double ω;//角频率


private Paint mPaint;//主画笔 private Path mPath;//主路径 private Path mReflexPath;//镜像路径 private ValueAnimator mAnimator;private int mHeight;private int mWidth;


public RhythmView(Context context) {this(context, null);}


public RhythmView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();//初始化}


private void init() {//初始化主画笔 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(Color.BLUE);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(dp(2));//初始化主路径 mPath = new Path();mReflexPath = new Path();//数字时间流 mAnimator = ValueAnimator.ofFloat(0, (float) (2 * Math.PI));mAnimator.setDuration(1000);mAnimator.setRepeatMode(ValueAnimator.RESTART);mAnimator.setInterpolator(new LinearInterpolator());mAnimator.addUpdateListener(a -> {φ = (float) a.getAnimatedValue();A = (float) (mMaxHeight * mPerHeight * (1 - (float) a.getAnimatedValue() / (2 * Math.PI)));invalidate();});}


public void setPerHeight(double perHeight) {mPerHeight = perHeight;mAnimator.start();}


@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mWidth = MeasureSpec.getSize(widthMeasureSpec);mHeight = MeasureSpec.getSize(heightMeasureSpec);mMaxHeight = mHeight / 2 * 0.9;min = -mWidth / 2;max = mWidth / 2;handleColor();setMeasuredDimension(mWidth, mHeight);}


private void handleColor() {int[] colors = new int[]{Color.parseColor("#33F60C0C"),//红 Color.parseColor("#F3B913"),//橙 Color.parseColor("#E7F716"),//黄 Color.parseColor("#3DF30B"),//绿 Color.parseColor("#0DF6EF"),//青 Color.parseColor("#0829FB"),//蓝 Color.parseColor("#33B709F4"),//紫};


float[] pos = new float[]{1.f / 10, 2.f / 7, 3.f / 7, 4.f / 7, 5.f / 7, 9.f / 10, 1};


mPaint.setShader(new LinearGradient((int) min, 0, (int) max, 0,colors, pos,Shader.TileMode.CLAMP));}


@Overrideprotected void onDraw(Canvas canvas) {mPath.reset();mReflexPath.reset();super.onDraw(canvas);canvas.save();canvas.translate(mWidth / 2, mHeight / 2);formPath();mPaint.setAlpha(255);canvas.drawPath(mPath, mPaint);mPaint.setAlpha(66);canvas.drawPath(mReflexPath, mPaint);canvas.restore();}


/**


  • 对应法则

  • @param x 原像(自变量)

  • @return 像(因变量)*/private double f(double x) {double len = max - min;double a = 4 / (4 + Math.pow(rad(x / Math.PI * 800 / len), 4));double aa = Math.pow(a, 2.5);ω = 2 * Math.PI / (rad(len) / 2);double y = aa * A * Math.sin(ω * rad(x) - φ);return y;}


private void formPath() {mPath.moveTo((float) min, (float) f(min));mReflexPath.moveTo((float) min, (float) f(min));for (double x = min; x <= max; x++) {double y = f(x);mPath.lineTo((float) x, (float) y);mReflexPath.lineTo((float) x, -(float) y);}


}


private double rad(double deg) {return deg / 180 * Math.PI;}


protected float dp(float dp) {return TypedValue.applyDime


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


nsion(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());}


}



五、MediaRecode 实现录音

第一天用AudioTrack实现了录音,MediaRecode 可以录音也可以录视频

两者的区别AudioTrack麻烦一点,需要自己去操作字节流,但可以精致操作

MediaRecode 相当于给你封装好了,你一步步走,给个文件就行了




1.录音的辅助类

/**


  • 作者:张风捷特烈

  • 时间:2018/4/16:10:33

  • 邮箱:1981462002@qq.com

  • 说明:MediaRecorder 录音帮助类*/public class MediaRecorderTask {private MediaRecorder mRecorder;private long mStartTime;//开始的时间 private int mAllTime;//总共耗时 private boolean isRecording;//是否正在录音 private File mFile;//文件


private Timer mTimer;private final Handler mHandler;


public MediaRecorderTask() {mTimer = new Timer();//创建 TimermHandler = new Handler();//创建 Handler}


/**


  • 开始录音*/public void start(File file) {mAllTime = 0;mFile = file;if (mRecorder == null) {// [1]获取 MediaRecorder 类的实例 mRecorder = new MediaRecorder();}//配置 MediaRecorder// [2]设置音频的来源 mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// [3]设置音频的输出格式 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// [4]采样频率 mRecorder.setAudioSamplingRate(44100);// [5]设置音频的编码方式 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//[6]音质编码频率:96KbpsmRecorder.setAudioEncodingBitRate(96000);//[7]设置录音文件位置 mRecorder.setOutputFile(file.getAbsolutePath());try {mRecorder.prepare();} catch (IOException e) {e.printStackTrace();}mStartTime = System.currentTimeMillis();if (mRecorder != null) {mRecorder.start();isRecording = true;


cbkVolume();}}


/**


  • 每隔 1 秒回调一次音量*/private void cbkVolume() {mTimer.schedule(new TimerTask() {@Overridepublic void run() {if (isRecording) {float per;try {//获取音量大小 per = mRecorder.getMaxAmplitude() / 32767f;//最大 32767} catch (IllegalStateException e) {e.printStackTrace();per = (float) Math.random();}if (mOnVolumeChangeListener != null) {float finalPer = per;mHandler.post(() -> {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android自定义控件(神级)+MediaRecoder录音,android开发基础应用