Android 自定義Camera(二)

經過上一篇 Android 自定義Camera(一) 的介紹,咱們已經能夠完成一個可拍照的基礎demo, 固然其中也有不少要注意的細節問題,好比預覽方向,設置預覽比例和返回圖片的比例等等問題,詳情能夠看上一篇博客,此次我會豐富相機的功能加入 閃光燈模式,正方形拍攝,延遲拍攝和先後攝像頭切換功能,接下來就一個一個開始吧。(下面會有完整源碼地址git

閃光燈模式

相機的閃光燈模式有三種, 自動,關閉, 打開, 代碼也 比較好理解,在拍照以前切換調用就能夠,個別地方加了註釋,這裏我貼上代碼: 1 關閉狀況:github

/**
     * 關閉閃光燈
     *
     * @param mCamera
     */
    public void turnLightOff(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        //獲取手機支持的模式
        List<String> flashModes = parameters.getSupportedFlashModes();
        String flashMode = parameters.getFlashMode();
        // Check if camera flash exists
        if (flashModes == null) {
            return;
        }
        if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
            // Turn off the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }
複製代碼

2 自動模式:canvas

/**
     * 自動模式閃光燈
     *
     * @param mCamera
     */
    public void turnLightAuto(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        // Check if camera flash exists
        if (flashModes == null) {
            // Use the screen as a flashlight (next best thing)
            return;
        }
        String flashMode = parameters.getFlashMode();
        if (!Camera.Parameters.FLASH_MODE_AUTO.equals(flashMode)) {
            // Turn on the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }
複製代碼

3 關閉模式bash

/**
     * 打開閃關燈
     *
     * @param mCamera
     */
    public void turnLightOn(Camera mCamera) {
        if (mCamera == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        if (parameters == null) {
            return;
        }
        List<String> flashModes = parameters.getSupportedFlashModes();
        // Check if camera flash exists
        if (flashModes == null) {
            // Use the screen as a flashlight (next best thing)
            return;
        }
        String flashMode = parameters.getFlashMode();
        if (!Camera.Parameters.FLASH_MODE_ON.equals(flashMode)) {
            // Turn on the flash
            if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                mCamera.setParameters(parameters);
            } else {
            }
        }
    }
複製代碼

正方形拍攝

這裏我要說一下我怎麼作的,目前我認爲 因爲咱們取景框的比例必須知足手機支持的尺寸,還有surfaceView和預覽尺寸的比例也要同樣,這樣其實咱們並不能肯定取景框的大小具體是多少,因此我實現正方形拍攝用的是 遮蓋取景框 的方式, 拍攝的時候將取景框遮住讓其成正方形, 在返回圖片的時候再將其裁剪成正方形便可, 目前在正式項目中我也在這樣用,由於不少手機都直接支持正方形尺寸, 這裏我用了倆個屬性動畫來遮蓋取景框, 代碼以下, 這裏主要是計算一下要遮住的高度ide

/**
     * 正方形拍攝
     */
    public void camera_square_0() {
        camera_square.setImageResource(R.drawable.btn_camera_size1_n);

        //屬性動畫
        ValueAnimator anim = ValueAnimator.ofInt(0, animHeight);
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = Integer.parseInt(animation.getAnimatedValue().toString());
                RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                Params.setMargins(0, SystemUtils.dp2px(context, 44), 0, 0);
                homeCustom_cover_top_view.setLayoutParams(Params);

                RelativeLayout.LayoutParams bottomParams = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                bottomParams.setMargins(0, screenHeight - menuPopviewHeight - currentValue, 0, 0);
                homeCustom_cover_bottom_view.setLayoutParams(bottomParams);
            }

        });
        anim.start();

        homeCustom_cover_top_view.bringToFront();
        home_custom_top_relative.bringToFront();
        homeCustom_cover_bottom_view.bringToFront();
        index++;
    }

    /**
     * 長方形方形拍攝
     */
    public void camera_square_1() {
        camera_square.setImageResource(R.drawable.btn_camera_size2_n);

        ValueAnimator anim = ValueAnimator.ofInt(animHeight, 0);
        anim.setDuration(300);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentValue = Integer.parseInt(animation.getAnimatedValue().toString());
                RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                Params.setMargins(0, SystemUtils.dp2px(context, 44), 0, 0);
                homeCustom_cover_top_view.setLayoutParams(Params);

                RelativeLayout.LayoutParams bottomParams = new RelativeLayout.LayoutParams(screenWidth, currentValue);
                bottomParams.setMargins(0, screenHeight - menuPopviewHeight - currentValue, 0, 0);
                homeCustom_cover_bottom_view.setLayoutParams(bottomParams);
            }
        });
        anim.start();
        index = 0;
    }
複製代碼

延遲拍攝

先說一下延遲拍攝的原理, 其實實現方式也不止一種的,這裏我使用了線程加handler的方式,核心代碼以下,先是記錄了一個延遲時間,而後遞減這個時間每隔1s, 最後它等於0的時候執行拍攝代碼, 效果我就不貼啦,能夠下載代碼運行看, 就是一個大大的數字在屏幕上讀秒動畫

new Thread(new Runnable() {
                            @Override
                            public void run() {
                                while (delay_time > 0) {
                                    //按秒數倒計時
                                    try {
                                        Thread.sleep(1000);
                                    } catch (InterruptedException e) {
                                        mHandler.sendEmptyMessage(AppConstant.WHAT.ERROR);
                                        return;
                                    }
                                    delay_time--;
                                    mHandler.sendEmptyMessage(AppConstant.WHAT.SUCCESS);
                                }
                            }
                        }).start();
複製代碼

切換前置後置攝像頭

幾乎全部的相機程序都須要這個功能,必需要能前置和後置啊,那這個其實實現起來也比較的簡單,當相機正在預覽過程當中進行先後置切換的時候必定要先釋放相機資源, 而後再開啓預覽, 切換攝像頭無非就是切換cameraId, 這裏先看下代碼:ui

public void  switchCamera() {
        releaseCamera();
        //這個方法getNumberOfCameras()是從API Level 9 引入的, 取得攝像頭個數 通常的正常手機只有一個攝像頭, 這裏我也先按照一個攝像頭處理了
        mCameraId = (mCameraId + 1) % mCamera.getNumberOfCameras();
        mCamera = getCamera(mCameraId);
        if (mHolder != null) {
            startPreview(mCamera, mHolder);
        }
    }
複製代碼

加水印

順便也說一下加水印的功能吧, 加水印功能上實現起來不難,可貴是要畫好看的水印哈哈, 其實加水印也是在拍照返回的bitmap上加入的, 其實就是用Canvas類畫上去,核心代碼以下, 假設拍照返回的圖爲bitmap:spa

Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(tempbitmap, left, top, paint);
複製代碼

代碼大致就是這樣,經過canvas.drawBitmap方法畫上去的, 這個固然就隨意的畫了, 記錄預覽時水印的位置,而後畫上去妥妥的。線程

OK, 這篇博客就到這裏了, 接下來我會研究Camera2, 據說增長了好玩的功能。code

下面是源碼地址:

github.com/jinguangyue… Star一下不虧.

相關文章
相關標籤/搜索