在同一個界面實現(xiàn)短按拍照和長按錄制視頻

以前項目中拍照和錄像是分開的,現(xiàn)在有個需求是仿照微信,把拍照和錄制視頻合并,實現(xiàn)短按拍照,長按錄像。之前看到過一個開源庫 JCamera ,這個基本已經(jīng)實現(xiàn)了,但是沒仔細看過代碼,于是從github上把代碼clone到本地,結(jié)合公司項目,把源碼進行了一部分修改。關于JCamera,網(wǎng)上可以搜到它的介紹和用法,這里就不多說了,現(xiàn)在說一下自己遇到的一些問題和解決方案。

1、JCamera基本可以滿足短按拍照和長按錄制視頻的需求,但是存在一些小問題,在項目中是需要解決的
a.部分機型是可以支持鏡頭的縮放問題
b.部分機型開始錄像和結(jié)束錄像都有個系統(tǒng)的“滴”的一聲
針對第一個問題,源碼中的判斷如下

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;
        }

    }

這樣之后就可以進行縮放鏡頭了

第二個問題,錄像的開始和結(jié)束會播放一下系統(tǒng)的“滴”的一聲,這個著實是頭疼了,沒找到什么好的解決方案,再一個因為項目中以前在錄像本身就進行了一個android系統(tǒng)版本的判斷,5.0以上使用最新的Camera2 API,5.0以下還是用以前的Camera。使用Camera2是不存在這個問題的,JCamera并沒有使用 Camera2,自己對Camera2不太了解,而且錄像功能一開始不是自己著手做的,現(xiàn)在只是根據(jù)需求進行功能優(yōu)化。所以沒辦法,為了解決這個問題,只能找一些關于Camera2的使用介紹。5.0一下使用JCamera,5.0以上使用Camera2。

關于Camera2,網(wǎng)上的一些資料并不是很多,而最快的了解使用方式就是通過Demo,看看別人怎么對API進行使用的。搜到一篇簡書上介紹Camera2的文章http://www.itdecent.cn/p/f8c694a4fb57,也是在同一個界面進行長按錄像和短按拍照的操作,于是下載下來進行了一番研究,由于作者對拍攝結(jié)果并沒有做過多的處理,不過,對于我來說,完全可以在這個基礎上進行更進一步的處理了。

處理過程中遇到的問題:
a.UI上使用和微信類似的樣式
b.功能上,拍照和錄像之間來回切換會崩潰問題
c.上下滑動縮放問題

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

b.這個沒好的方法,只能根據(jù)log日志進行問題定位,和不斷的調(diào)試,不懂的搜一下網(wǎng)上別的小伙伴怎么解決的。這個耗費了我兩三天,過程真的是爽歪歪的。

c.對于Camera2的縮放問題,網(wǎng)上說的都是兩指縮放,這個在拍照的時候可以雙指,在錄制的時候,是需要上下滑動進行縮放鏡頭的,我的解決方法是,按下拍的時候,是可以確定一個點的做一個全局變量,然后與滑動的位置點進行配合處理,這樣就可以類似雙指動作了。關鍵代碼如下:

@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;        //修改當前狀態(tài)為點擊按下

                //判斷按鈕狀態(tài)是否為可錄制狀態(tài)
                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) {
                    //活動區(qū)域?qū)挾群妥魑飬^(qū)域?qū)挾戎群突顒訁^(qū)域高度和作物區(qū)域高度之比的最大比率
                    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);
                        //調(diào)用縮放回調(diào)接口
                        captureListener.recordZoom(zoom);
                    }
                    finger_spacing = current_finger_spacing;
                }
                break;
            case MotionEvent.ACTION_UP:
                //根據(jù)當前按鈕的狀態(tài)進行相應的處理
                handlerUnpressByState();
                break;
        }
        return true;
    }

最終實現(xiàn)了個5.0一下使用JCamera,5.0以上使用Camera2 的效果。抽空做了個demo,上傳到了CSDN上,demo下載需要5積分,下載地址https://download.csdn.net/my,當然大家也可以到github上下載免費的,demo地址:
https://github.com/Alvin9234/CaptureDemo

歡迎大家一起討論,共同學習

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容