在同一个界面实现短按拍照和长按录制视频

以前项目中拍照和录像是分开的,现在有个需求是仿照微信,把拍照和录制视频合并,实现短按拍照,长按录像。之前看到过一个开源库 JCamera ,这个基本已经实现了,但是没仔细看过代码,于是从github上把代码clone到本地,结合公司项目,把源码进行了一部分修改。关于JCamera,网上可以搜到它的介绍和用法,这里就不多说了,现在说一下自己遇到的一些问题和解决方案。

1、JCamera基本可以满足短按拍照和长按录制视频的需求,但是存在一些小问题,在项目中是需要解决的
a.部分机型是可以支持镜头的缩放问题
b.部分机型开始录像和结束录像都有个系统的“滴”的一声
针对第一个问题,源码中的判断如下

if (!mParams.isZoomSupported() || !mParams.isSmoothZoomSupported()) {
   return;
}

isZoomSupported()是判断设备是否支持缩放,isSmoothZoomSupported()是判断是否支持平滑缩放,android的部分机型这两个返回一个是:isZoomSupported()放回true,isSmoothZoomSupported()返回false,也就是说支持缩放,但是不支持平滑缩放,于是我把setZoom() 方法改成了:

public void setZoom(float zoom, int type) {
        if (mCamera == null) {
            return;
        }
        if (mParams == null) {
            mParams = mCamera.getParameters();
        }
        /*if (!mParams.isZoomSupported() || !mParams.isSmoothZoomSupported()) {
            return;
        }*/
        if (!mParams.isZoomSupported()) {
            return;
        }
        switch (type) {
            case TYPE_RECORDER:
                //如果不是录制视频中,上滑不会缩放
                if (!isRecorder) {
                    return;
                }
                if (zoom >= 0) {
                    //每移动50个像素缩放一个级别
                    int scaleRate = (int) (zoom / 40);
                    float getMaxZoom = mParams.getMaxZoom();
                    if (scaleRate <= getMaxZoom && scaleRate >= nowScaleRate && recordScleRate != scaleRate) {
                        if(mParams.isSmoothZoomSupported()){
                            mCamera.startSmoothZoom(scaleRate);
                        }else{
                            if(scaleRate+10<=getMaxZoom){
                                mParams.setZoom(scaleRate+10);
                            }else{
                                mParams.setZoom((int)getMaxZoom);
                            }

                            mCamera.setParameters(mParams);
                        }
                        recordScleRate = scaleRate;
                    }
                }
                break;
            case TYPE_CAPTURE:
                if (isRecorder) {
                    return;
                }
                //每移动50个像素缩放一个级别
                int scaleRate = (int) (zoom / 50);
                if (scaleRate < mParams.getMaxZoom()) {
                    nowScaleRate += scaleRate;
                    if (nowScaleRate < 0) {
                        nowScaleRate = 0;
                    } else if (nowScaleRate > mParams.getMaxZoom()) {
                        nowScaleRate = mParams.getMaxZoom();
                    }
                    if(mParams.isSmoothZoomSupported()){
                        mCamera.startSmoothZoom(nowScaleRate);
                    }else{
                        mParams.setZoom(nowScaleRate);
                        mCamera.setParameters(mParams);
                    }
                }
                Log.i("","setZoom = " + nowScaleRate);
                break;
        }

    }

这样之后就可以进行缩放镜头了

第二个问题,录像的开始和结束会播放一下系统的“滴”的一声,这个着实是头疼了,没找到什么好的解决方案,再一个因为项目中以前在录像本身就进行了一个android系统版本的判断,5.0以上使用最新的Camera2 API,5.0以下还是用以前的Camera。使用Camera2是不存在这个问题的,JCamera并没有使用 Camera2,自己对Camera2不太了解,而且录像功能一开始不是自己着手做的,现在只是根据需求进行功能优化。所以没办法,为了解决这个问题,只能找一些关于Camera2的使用介绍。5.0一下使用JCamera,5.0以上使用Camera2。

关于Camera2,网上的一些资料并不是很多,而最快的了解使用方式就是通过Demo,看看别人怎么对API进行使用的。搜到一篇简书上介绍Camera2的文章https://www.jianshu.com/p/f8c694a4fb57,也是在同一个界面进行长按录像和短按拍照的操作,于是下载下来进行了一番研究,由于作者对拍摄结果并没有做过多的处理,不过,对于我来说,完全可以在这个基础上进行更进一步的处理了。

处理过程中遇到的问题:
a.UI上使用和微信类似的样式
b.功能上,拍照和录像之间来回切换会崩溃问题
c.上下滑动缩放问题

解决方案:
a.UI上,可以使用JCamera的就可以了,可以使用里面封装的控件,在基础上修改就可以

b.这个没好的方法,只能根据log日志进行问题定位,和不断的调试,不懂的搜一下网上别的小伙伴怎么解决的。这个耗费了我两三天,过程真的是爽歪歪的。

c.对于Camera2的缩放问题,网上说的都是两指缩放,这个在拍照的时候可以双指,在录制的时候,是需要上下滑动进行缩放镜头的,我的解决方法是,按下拍的时候,是可以确定一个点的做一个全局变量,然后与滑动的位置点进行配合处理,这样就可以类似双指动作了。关键代码如下:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.i("","state = " + state);
                if (event.getPointerCount() > 1 || state != STATE_IDLE)
                    break;
                state = STATE_PRESS;        //修改当前状态为点击按下

                //判断按钮状态是否为可录制状态
                if ((button_state == BUTTON_STATE_ONLY_RECORDER || button_state == BUTTON_STATE_BOTH))
                    postDelayed(longPressRunnable, 500);    //同时延长500启动长按后处理的逻辑Runnable
                break;
            case MotionEvent.ACTION_MOVE:
                if (captureListener != null
                        && (state == STATE_RECORDERING)
                        && (button_state == BUTTON_STATE_ONLY_RECORDER || button_state == BUTTON_STATE_BOTH)
                        && cameraCharacteristics!=null && event.getY()<center_Y-10) {
                    //活动区域宽度和作物区域宽度之比和活动区域高度和作物区域高度之比的最大比率
                    float maxZoom = (cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)) * 10;
                    Rect m = cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
                    float current_finger_spacing;
                    //计算两个触摸点的距离
                    current_finger_spacing = getFingerSpacing(event);

                    if (finger_spacing != 0) {
                        if (current_finger_spacing > finger_spacing && maxZoom > zoom_level) {
                            zoom_level++;

                        } else if (current_finger_spacing < finger_spacing && zoom_level > 1) {
                            zoom_level--;
                        }

                        int minW = (int) (m.width() / maxZoom);
                        int minH = (int) (m.height() / maxZoom);
                        int difW = m.width() - minW;
                        int difH = m.height() - minH;
                        int cropW = difW / 100 * zoom_level;
                        int cropH = difH / 100 *  zoom_level;
                        cropW -= cropW & 3;
                        cropH -= cropH & 3;
                        zoom = new Rect(cropW, cropH, m.width() - cropW, m.height() - cropH);
                        //调用缩放回调接口
                        captureListener.recordZoom(zoom);
                    }
                    finger_spacing = current_finger_spacing;
                }
                break;
            case MotionEvent.ACTION_UP:
                //根据当前按钮的状态进行相应的处理
                handlerUnpressByState();
                break;
        }
        return true;
    }

最终实现了个5.0一下使用JCamera,5.0以上使用Camera2 的效果。抽空做了个demo,上传到了CSDN上,demo下载需要5积分,下载地址https://download.csdn.net/my,当然大家也可以到github上下载免费的,demo地址:
https://github.com/Alvin9234/CaptureDemo

欢迎大家一起讨论,共同学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容