Android中仿微信语音竖线动画2

 自定义View实现仿微信语音竖线动画

package com.sample.utils;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;

public class AudioRecorder {

    private int bufferSize;
    private AudioRecord audioRecord;
    private boolean isRecording;
    private Object mLock;
    public AudioRecorder() {
        mLock = new Object();
        int sampleRate = 44100; // 采样率
        int channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道
        //channelConfig = AudioFormat.CHANNEL_IN_STEREO;//立体声
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 格式
        bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize);
    }

    public void startRecording() {
        isRecording = true;
        new Thread(new Runnable() {
            @Override
            public void run() {
                audioRecord.startRecording();
                byte[] buffer = new byte[bufferSize];
                while (isRecording) {
                    int read = audioRecord.read(buffer, 0, bufferSize);
                    long v = 0;
                    // 将 buffer 内容取出,进行平方和运算
                    for (int i = 0; i < buffer.length; i++) {
                        v += buffer[i] * buffer[i];
                    }
                    // 平方和除以数据总长度,得到音量大小。
                    double mean = v / (double) read;
                    double volume = 10 * Math.log10(mean);
                    System.out.println("分贝值:" + volume);
                    listener.getAudioVolume(volume);
                    listener.getAudioVolume(buffer);
                    // 大概一秒十次
                    synchronized (mLock) {
                        try {
                            mLock.wait(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).start();
    }
    public void stopRecording() {
        isRecording = false;
        if (audioRecord!=null)
            audioRecord.stop();
        //audioRecord.release();
    }
    AudioListener listener;
    public interface AudioListener{
        void getAudioVolume(double volume);
        void getAudioVolume(byte[] buffer);
    }
    public void setListener(AudioListener listener){
        this.listener = listener;
    }
}
package com.sample.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.sample.R;

import java.util.Random;


public class TestDraw extends View {
    private Context context;
    private Paint linePaint;
    private int width,height;//屏幕的宽、高
    Matrix matrix;
    float downX,downY,lastX,lastY;
    private boolean pointer;// 是否多个手指
    private float[] matrixValue= new float[9];// matrix对应的值
    public TestDraw(Context context) {
        super(context);
        this.context = context;
        initPaint();
    }

    public TestDraw(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initPaint();
    }

    public TestDraw(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        initPaint();
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public TestDraw(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        this.context = context;
        initPaint();
    }
    private void initPaint() {
        linePaint = new Paint();
        //画笔抗锯齿
        linePaint.setAntiAlias(true);
        initScaleGestureDetector();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //视图的宽高
        width = w;
        height = h;
        System.out.println("宽:"+w+"高:"+h);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.concat(matrix);
        canvas.drawColor(getResources().getColor(R.color.hint_color));
        // 去除锯齿毛边
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG));
        testDraw2(canvas);
        ViewConfiguration.get(context).getScaledTouchSlop();
    }
    float minHeight = 0;
    float maxHeight = 0;
    float startY = 40;
    float stopY = 0;
    Random random = new Random();
    private void testDraw2(Canvas canvas){
        stopY = height-40;
        maxHeight = stopY-startY;
        minHeight = maxHeight/6;
        float startX = (width-10*40)/2;
        for (int a=0;a<40;a++){
            if (volume<=voiceMin){
                num = 0;
                //最小
                drawLine(canvas,startX+a*10,(height-minHeight)/2,startX+a*10,(height-minHeight)/2+minHeight);
            }else if (voiceMin<volume&&volume<voiceMax){
                if (a<a1||a>a2){
                    //最小
                    drawLine(canvas,startX+a*10,(height-minHeight)/2,startX+a*10,(height-minHeight)/2+minHeight);
                }else{
                    float x = startX+a*10;
                    int i = random.nextInt(a2-a1)+a1;
                    float h = 5*i/2;
                    if (h>maxHeight){
                        if (volume>voice)
                            h = maxHeight;
                        else
                            h = maxHeight-10;
                    }
                    float y1 = (height-h)/2;
                    float y2 = (height-h)/2+h;
                    drawLine(canvas,x,y1,x,y2);
                }
            }else{
                //最大
                drawLine(canvas,startX+a*10,(height-maxHeight)/2,startX+a*10,(height-maxHeight)/2+maxHeight);
            }
        }
    }
    private void drawLine(Canvas canvas,
                          float startX,float startY,float stopX,float stopY){
        linePaint.setStyle(Paint.Style.STROKE);//不加这个不显示
        linePaint.setColor(getResources().getColor(R.color.mywhite));
        linePaint.setStrokeWidth(6);
        Path mPath = new Path();
        float sX = startX;
        float sY = startY;
        float sX2 = stopX;
        float sY2 = stopY;
        mPath.moveTo(sX, sY);
        mPath.lineTo(sX2, sY2);
        mPath.close();
        canvas.drawPath(mPath, linePaint);
    }
    private void initScaleGestureDetector() {
        matrix = new Matrix();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //拖动监听
        int x = (int) event.getX();
        int y = (int) event.getY();
        if (event.getPointerCount() > 1) {
            pointer = true;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://第一个手指初次碰到屏幕触发
                downX = x;
                downY = y;
                System.out.println("ACTION_DOWN...");
                pointer = false;
                listener.audioStart();
                break;
            case MotionEvent.ACTION_UP://最后一个手指离开屏幕触发
                float upX = (float) Math.abs(x - downX);
                float upY = (float) Math.abs(y - downY);
                if (y<downY&&upY > 100 && !pointer) {
                    System.out.println("ACTION_UP...松手取消");
                    listener.audioStop();
                }
                break;
            case MotionEvent.ACTION_MOVE://手指在屏幕上滑动
                float dx = (float) Math.abs(x - downX);
                float dy = (float) Math.abs(y - downY);
                if (y<downY&&dy > 100 && !pointer) {
                    System.out.println("ACTION_MOVE...");
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN://有非主要的手指按下(按下之前已经有手指在屏幕上)
                System.out.println("ACTION_POINTER_DOWN...");
                break;
            case MotionEvent.ACTION_POINTER_UP://有非主要手指抬起(抬起之后还有手指在屏幕上)
                System.out.println("ACTION_POINTER_UP...");
                break;
        }
        lastX = x;
        lastY = y;
        return true;
    }
    double volume;
    int num = 0;//次数
    int a1 = 10,a2 = 30;
    //30、40是根据手机自带录音获取到的分贝范围
    double voiceMin = 30,voice = 34.5,voiceMax = 40;
    public void getVolume(double volume){
        this.volume = volume;
        if (voiceMin<volume&&volume<voiceMax)
            num++;
        int i = num>0?random.nextInt(num):0;
        if (20<i&&i<50){
            a1 = 5;a2 = 35;
        }else if (i>50){
            num = 0;
            a1 = 3;a2 = 37;
        }else{
            a1 = 10;a2 = 30;
        }
        invalidate();
    }

    AudioListener listener;
    public interface AudioListener{
        void audioStart();
        void audioStop();
    }
    public void setListener(AudioListener listener){
        this.listener = listener;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现Android仿微信语音通话的效果,你可以按照以下步骤进行操作: 1. 首先,在styles.xml文件中定义一个自定义的对话框主题,可以参考引用\[1\]中的代码。这个主题可以设置对话框的背景透明、无边框、浮现在activity之上以及背景模糊显示等效果。 2. 在strings.xml文件中定义三个字符串资源,分别表示正常录音状态、录音中状态和取消发送状态。可以参考引用\[2\]中的代码。 3. 在布局文件中创建一个用于显示语音通话的界面,可以使用一个ImageView显示语音图标,一个TextView显示录音状态,以及一个Button用于开始和结束录音。 4. 在Activity中,根据用户的操作来改变TextView的文本内容,以及根据录音状态来改变ImageView的图标。 5. 使用MediaRecorder类来实现录音功能,可以在Button的点击事件中开始和结束录音。 6. 使用AudioManager类来控制音频的播放和停止,可以在Activity的生命周期方法中进行相应的操作。 通过以上步骤,你可以实现一个仿微信语音通话的效果。记得根据你的具体需求进行适当的修改和调整。 #### 引用[.reference_title] - *1* *2* [Android 仿微信实现语音聊天功能](https://blog.csdn.net/lhk147852369/article/details/78658055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值