安卓原生聊天面板开发(三)录音交互实现

系列文章

安卓原生聊天面板开发(一)整体规划
安卓原生聊天面板开发(二)emoji功能实现
安卓原生聊天面板开发(三)录音交互实现
安卓原生聊天面板开发(四)整体交互实现

背景

产品喝大了,说开发一个聊天界面,功能参照微信即可。

这是应了那句话:新人一开口,便知有没有~~真是风趣幽默。

问题分析

其实仔细看微信的聊天面板,功能拆分出来,主要有以下几点:

(1)emoji表情,自定义表情等等。这里可以归类为"表情"tab。

(2)语音交互,音频录制播放压缩。

(3)媒体交互,选择图片,视频,文件等等。

核心就是上面的内容,锦上添花的功能就不再叙述了。

实现效果

开发环境

win10

jdk8+

as2024+

本文内容

本文将会讲解实现录音动画的最核心思路。文末将会有源码地址。

先看效果图

思路大纲

对于实现这种需求,正常的做法就是拆分,看看到底有哪些状态。

(1)没有录音

(2)录音中--手指在移动范围

(2)录音中--手指在超过范围

(4)录音结束

总体就是这四个小状态。而其中,难点就是动画的播放,特别是黑色提示框的显示与收起(插件是一个view,而提示框是一个全局的,可以是任何位置的view,有可能覆盖在输入框上面)

核心实现

(一)动画

动画的播放,这里选择的是svga,因为其轻量,保真度高,所以选这个。官方提供的示例代码中,有两种方式可以实现动画的播放:

(1)使用提供的控件,在xml布局中声明好相关属性,进行播放

(2)先加载资源文件生成一个svgadrawable,然后动态设置到控件中,进行处理。

博主选择了第二种。第二种的好处就是,可以复用,也可以按需加载,定制度高,而且还能有自己的动画对象管理。

加载svga文件核心代码如下:

复制代码
        mSvgaAnimManager.loadAssets(getContext(), ChatInputResConst.SVGA_RECORD, null, new SVGALoadListener() {
            @Override
            public void complete(SVGAVideoEntity entity) {
                //播放完成
                mSvgaDrawable = new SVGADrawable(entity);
                mSvgaInit = true;
            }

            @Override
            public void error() {
                //错误
            }
        });

暂停,开始播放相关代码:

复制代码
    private void startAnim() {
        if (!mSvgaInit || mSvgaAnimView == null) {
            return;
        }
        stopAnim();
        mSvgaAnimView.setImageDrawable(mSvgaDrawable);
        mSvgaAnimView.startAnimation();
    }

    private void stopAnim() {
        if (mSvgaAnimView == null) {
            return;
        }
        mSvgaAnimView.stopAnimation();
        mSvgaAnimView.setImageDrawable(null);
    }

在初始化的时候,就进行svga的资源获取,至于什么使用进行播放,就按需处理。这样做的最大好处,就是能够统一管理播放资源。

(二)黑色提示框

这个提示框,其实并不是在当前布局中实现的,因为不能贴合需求。

那么怎样能够让这个提示框,不再收到当前布局的约束?

答案就是decoreview

通过activity context,可以获取到一个DecoreView。至于DecoreView是什么,请自行百度,因为细节有很多细节。

那么有了这个DecoreView,我们是不是可以在里面,添加view(AddView),和移除view(removeView)了?

再者,结合view.getViewWindowLocation方法,就可以获取你想要显示的位置了。当然要注意的是,宽高获取以及处理。

请注意svga控件的用法,如播放完清空画布等操作

就是这么简单~~

(三)触摸事件的分发

需求就是,点击录音按钮,就做动画,移动超过了范围,就另作处理。

核心就是,子控件(录音按钮)只做一个触发,当收到按下的事件时,就开始录音,然后其父控件,做全部的事件分发处理,这些事件,都可以在父控件中捕获,前提是重写了父控件的事件分发方法。核心代码如下:

父控件分发:

复制代码
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                ChatLogUtils.log("root ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                dealMoveEvent(event);
                break;
            case MotionEvent.ACTION_UP:
                ChatLogUtils.log("root ACTION_UP");
                stopRecordEvent(mIsIntRange);
                break;
            case MotionEvent.ACTION_CANCEL:
                ChatLogUtils.log("root ACTION_CANCEL");
                stopRecordEvent(mIsIntRange);
                break;
        }
        return true;
    }

子控件分发:

复制代码
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                ChatLogUtils.log("button ACTION_DOWN");
                if (mListener != null) {
                    mListener.click();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                ChatLogUtils.log("button ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                ChatLogUtils.log("button ACTION_UP");
                break;
            case MotionEvent.ACTION_CANCEL:
                ChatLogUtils.log("button ACTION_CANCEL");
                break;
        }
        return super.onTouchEvent(event);
    }

(四)倒计时的实现

那么上面的事件分发,我们可以做到:开始,播放中,停止。这些周期的监听,那么倒计时也是一样的,在这些周期方法中,进行停止计时,开始计时,即可。

注意一个点,在按下的过程中,倒计时到头了,那么,也要处理好一个调整到初始状态的操作。

上述就是整个录音交互实现的思路,详细源码,文末可获取。

源码

源码获取方式,关注回复: 安卓原生聊天面板源码

即可获得:

相关推荐
alexhilton20 小时前
在Jetpack Compose中创建CRT屏幕效果
android·kotlin·android jetpack
2501_940094021 天前
emu系列模拟器最新汉化版 安卓版 怀旧游戏模拟器全集附可运行游戏ROM
android·游戏·安卓·模拟器
下位子1 天前
『OpenGL学习滤镜相机』- Day9: CameraX 基础集成
android·opengl
参宿四南河三1 天前
Android Compose SideEffect(副作用)实例加倍详解
android·app
火柴就是我1 天前
mmkv的 mmap 的理解
android
没有了遇见1 天前
Android之直播宽高比和相机宽高比不支持后动态获取所支持的宽高比
android
shenshizhong1 天前
揭开 kotlin 中协程的神秘面纱
android·kotlin
vivo高启强1 天前
如何简单 hack agp 执行过程中的某个类
android
沐怡旸1 天前
【底层机制】 Android ION内存分配器深度解析
android·面试
你听得到111 天前
肝了半个月,我用 Flutter 写了个功能强大的图片编辑器,告别image_cropper
android·前端·flutter