ANDROID 高仿微信拍照与视频拍摄(Camera+TextureView+rxjava)

1:需求分析
先上图看效果
《ANDROID 高仿微信拍照与视频拍摄(Camera+TextureView+rxjava)》

《ANDROID 高仿微信拍照与视频拍摄(Camera+TextureView+rxjava)》

a:拍照时,中间的拍照按钮稍微小些,单击可以拍照,长按时中间的拍照按钮变大,并有进度提示拍摄视频进度
b:中间区域可以手势缩放,单击时可以根据该点进行拍摄/拍照对焦,界面上显示对焦动画

《ANDROID 高仿微信拍照与视频拍摄(Camera+TextureView+rxjava)》

c:长按拍摄视频时手指在屏幕上上滑放大,下滑缩小焦距

d:拍完视频时界面上有刚才拍摄的视频预览效果,拍照完时显示拍的图片

2:对焦控件实现就是点击界面时有个绿色中间框由大变小的动画
不多说直接看主要代码

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = MotionEventCompat.getActionMasked(event);
        if (event.getPointerCount() == 1 && action == MotionEvent.ACTION_DOWN) {
            float x = event.getX();
            float y = event.getY();
            setFoucsPoint(x, y);
            if (listener != null) {
                listener.handleFocus(x, y);
            }
        } else if (event.getPointerCount() >= 2){
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_POINTER_DOWN:
                    oldDist = getFingerSpacing(event);
                    break;
                case MotionEvent.ACTION_MOVE:
                    float newDist = getFingerSpacing(event);
                    if (newDist > oldDist) {
                        if (this.listener != null) {
                            this.listener.handleZoom(true);
                        }
                    } else if (newDist < oldDist) {
                        if (this.listener != null) {
                            this.listener.handleZoom(false);
                        }
                    }
                    oldDist = newDist;
                    break;
            }
        }
        return true;
    }

/** * 设置当前触摸点 * @param x * @param y */
    private void setFoucsPoint(float x, float y) {
        if (subscription != null) {
            subscription.unsubscribe();
        }
        rectF.set(x - focusSize, y - focusSize, x + focusSize, y + focusSize);
        final int count = ANIM_MILS / ANIM_UPDATE;
        subscription = Observable.interval(ANIM_UPDATE, TimeUnit.MILLISECONDS).take(count).subscribe(new Subscriber<Long>() {
            @Override
            public void onCompleted() {
                scale = 0;
                postInvalidate();
            }

            @Override
            public void onError(Throwable e) {
                scale = 0;
                postInvalidate();
            }

            @Override
            public void onNext(Long aLong) {
                float current = aLong== null ? 0 : aLong.longValue();
                scale = 1 - current / count;
                if (scale <= 0.5f) {
                    scale = 0.5f;
                }
                postInvalidate();
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (scale != 0) {
            float centerX = rectF.centerX();
            float centerY = rectF.centerY();
            canvas.scale(scale, scale, centerX, centerY);
            canvas.drawRect(rectF, paint);
            canvas.drawLine(rectF.left, centerY, rectF.left + lineSize, centerY, paint);
            canvas.drawLine(rectF.right, centerY, rectF.right - lineSize, centerY, paint);
            canvas.drawLine(centerX, rectF.top, centerX, rectF.top + lineSize, paint);
            canvas.drawLine(centerX, rectF.bottom, centerX, rectF.bottom - lineSize, paint);
        }
    }

3:中间拍照与拍摄视频的按钮,长按放大并显示进度

直接上代码


 /** * 进度触摸监听 */
    public interface OnProgressTouchListener {
        /** * 单击 * @param progressBar */
        void onClick(CameraProgressBar progressBar);

        /** * 长按 * @param progressBar */
        void onLongClick(CameraProgressBar progressBar);

        /** * 移动 * @param zoom true放大 */
        void onZoom(boolean zoom);

        /** * 长按抬起 * @param progressBar */
        void onLongClickUp(CameraProgressBar progressBar);

        /** * 触摸对焦 * @param rawX * @param rawY */

        void onPointerDown(float rawX, float rawY);
    }


private void init(Context context, AttributeSet attrs) {
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        if (attrs != null) {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CameraProgressBar);
            innerColor = a.getColor(R.styleable.CameraProgressBar_innerColor, innerColor);
            outerColor = a.getColor(R.styleable.CameraProgressBar_outerColor, outerColor);
            progressColor = a.getColor(R.styleable.CameraProgressBar_progressColor, progressColor);
            innerRadio = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_innerRadio, innerRadio);
            progressWidth = a.getDimensionPixelOffset(R.styleable.CameraProgressBar_progressWidth, progressWidth);
            progress = a.getInt(R.styleable.CameraProgressBar_progress, progress);
            scale = a.getFloat(R.styleable.CameraProgressBar_scale, scale);
            isLongScale = a.getBoolean(R.styleable.CameraProgressBar_isLongScale, isLongScale);
            maxProgress = a.getInt(R.styleable.CameraProgressBar_maxProgress, maxProgress);
            a.recycle();
        }
        backgroundPaint = new Paint();
        backgroundPaint.setAntiAlias(true);
        backgroundPaint.setColor(backgroundColor);

        progressPaint = new Paint();
        progressPaint.setAntiAlias(true);
        progressPaint.setStrokeWidth(progressWidth);
        progressPaint.setStyle(Paint.Style.STROKE);

        innerPaint = new Paint();
        innerPaint.setAntiAlias(true);
        innerPaint.setStrokeWidth(innerRadio);
        innerPaint.setStyle(Paint.Style.STROKE);

        sweepAngle = ((float) progress / maxProgress) * 360;

        mDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                isLongClick = false;
                if (CameraProgressBar.this.listener != null) {
                    CameraProgressBar.this.listener.onClick(CameraProgressBar.this);
                }
                return super.onSingleTapConfirmed(e);
            }

            @Override
            public void onLongPress(MotionEvent e) {
                isLongClick = true;
                postInvalidate();
                mLastY = e.getY();
                if (CameraProgressBar.this.listener != null) {
                    CameraProgressBar.this.listener.onLongClick(CameraProgressBar.this);
                }
            }
        });
        mDetector.setIsLongpressEnabled(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (width > height) {
            setMeasuredDimension(height, height);
        } else {
            setMeasuredDimension(width, width);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth();
        float circle = width / 2.0f;

        if (/*isLongScale && */!isLongClick) {
            canvas.scale(scale, scale, circle, circle);
        }


        //画内圆
        float backgroundRadio = circle - progressWidth - innerRadio;
        canvas.drawCircle(circle, circle, backgroundRadio, backgroundPaint);

        //画内外环
        float halfInnerWidth = innerRadio / 2.0f + progressWidth;
        RectF innerRectF = new RectF(halfInnerWidth, halfInnerWidth, width - halfInnerWidth, width - halfInnerWidth);
        canvas.drawArc(innerRectF, -90, 360, true, innerPaint);

        progressPaint.setColor(outerColor);
        float halfOuterWidth = progressWidth / 2.0f;
        RectF outerRectF = new RectF(halfOuterWidth, halfOuterWidth, getWidth() - halfOuterWidth, getWidth() - halfOuterWidth);
        canvas.drawArc(outerRectF, -90, 360, true, progressPaint);

        progressPaint.setColor(progressColor);
        canvas.drawArc(outerRectF, -90, sweepAngle, false, progressPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isLongScale) {
            return super.onTouchEvent(event);
        }
        this.mDetector.onTouchEvent(event);
        switch(MotionEventCompat.getActionMasked(event)) {
            case MotionEvent.ACTION_DOWN:
                isLongClick = false;
                isBeingDrag = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isLongClick) {
                    float y = event.getY();
                    if (isBeingDrag) {
                        boolean isUpScroll = y < mLastY;
                        mLastY = y;
                        if (this.listener != null) {
                            this.listener.onZoom(isUpScroll);
                        }
                    } else {
                        isBeingDrag = Math.abs(y - mLastY) > mTouchSlop;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isBeingDrag = false;
                if (isLongClick) {
                    isLongClick = false;
                    postInvalidate();
                    if (this.listener != null) {
                        this.listener.onLongClickUp(this);
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                if (isLongClick) {
                    if (this.listener != null) {
                        this.listener.onPointerDown(event.getRawX(), event.getRawY());
                    }
                }
                break;
        }
        return true;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        Parcelable superData = super.onSaveInstanceState();
        bundle.putParcelable("superData", superData);
        bundle.putInt("progress", progress);
        bundle.putInt("maxProgress", maxProgress);
        return bundle;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        Bundle bundle = (Bundle) state;
        Parcelable superData = bundle.getParcelable("superData");
        progress = bundle.getInt("progress");
        maxProgress = bundle.getInt("maxProgress");
        super.onRestoreInstanceState(superData);
    }

    /** * 设置进度 * @param progress */
    public void setProgress(int progress) {
        if (progress <= 0) progress = 0;
        if (progress >= maxProgress) progress = maxProgress;
        if (progress == this.progress) return;
        this.progress = progress;
        this.sweepAngle = ((float) progress / maxProgress) * 360;
        postInvalidate();
    }

    /** * 还原到初始状态 */
    public void reset() {
        isLongClick = false;
        this.progress = 0;
        this.sweepAngle = 0;
        postInvalidate();
    }

    public int getProgress() {
        return progress;
    }

    public void setLongScale(boolean longScale) {
        isLongScale = longScale;
    }

    public void setMaxProgress(int maxProgress) {
        this.maxProgress = maxProgress;
    }

    private OnProgressTouchListener listener;

    public void setOnProgressTouchListener(OnProgressTouchListener listener) {
        this.listener = listener;
    }

4:Camera的初始化与对焦代码啦包括视频播放的代码啦,这类代码网上有很多,但是由于TextureView即要拍摄又要播放视频,所以不论是在拍照结束或录制结束时都要释放TextureView

CameraManager管理类

package you.xiaochen.camera;

import android.app.Application;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import you.xiaochen.utils.LogUtils;

/** * Created by you on 2016/10/22. * 相机管理类 */

public final class CameraManager {

    private Application context;
    /** * camera */
    private Camera mCamera;
    /** * 视频录制 */
    private MediaRecorder mMediaRecorder;
    /** * 相机闪光状态 */
    private int cameraFlash;
    /** * 前后置状态 */
    private int cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
    /** * 是否支持前置摄像,是否支持闪光 */
    private boolean isSupportFrontCamera, isSupportFlashCamera;
    /** * 录制视频的相关参数 */
    private CamcorderProfile mProfile;
    /** * 0为拍照, 1为录像 */
    private int cameraType;

    private CameraManager(Application context) {
        this.context = context;
        isSupportFrontCamera = CameraUtils.isSupportFrontCamera();
        isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context);
        if (isSupportFrontCamera) {
            cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK);
        }
        if (isSupportFlashCamera) {
            cameraFlash = CameraUtils.getCameraFlash(context);
        }
    }

    private static CameraManager INSTANCE;

    public static CameraManager getInstance(Application context) {
        if (INSTANCE == null) {
            synchronized (CameraManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new CameraManager(context);
                }
            }
        }
        return INSTANCE;
    }

    /** * 打开camera */
    public void openCamera(SurfaceTexture surfaceTexture, int width, int height) {
        if (mCamera == null) {
            mCamera = Camera.open(cameraFacing);//打开当前选中的摄像头
            mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH);
            try {
                mCamera.setDisplayOrientation(90);//默认竖直拍照
                mCamera.setPreviewTexture(surfaceTexture);
                initCameraParameters(cameraFacing, width, height);
                mCamera.startPreview();
            } catch (Exception e) {
                LogUtils.i(e);
                if (mCamera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    /** * 开启预览,前提是camera初始化了 */
    public void restartPreview() {
        if (mCamera == null) return;
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            int zoom = parameters.getZoom();
            if (zoom > 0) {
                parameters.setZoom(0);
                mCamera.setParameters(parameters);
            }
            mCamera.startPreview();
        } catch (Exception e) {
            LogUtils.i(e);
            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
        }
    }

    private void initCameraParameters(int cameraId, int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            List<String> focusModes = parameters.getSupportedFocusModes();
            if (focusModes != null) {
                if (cameraType == 0) {
                    if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                    }
                } else {
                    if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    }
                }
            }
        }
        parameters.setRotation(90);//设置旋转代码,
        switch (cameraFlash) {
            case 0:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                break;
            case 1:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                break;
            case 2:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                break;
        }
        List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) {
            /*for (Camera.Size size : pictureSizes) { LogUtils.i("pictureSize " + size.width + " " + size.height); } for (Camera.Size size : pictureSizes) { LogUtils.i("previewSize " + size.width + " " + size.height); }*/
            Camera.Size optimalPicSize = getOptimalSize(pictureSizes, width, height);
            Camera.Size optimalPreSize = getOptimalSize(previewSizes, width, height);
            LogUtils.i("TextureSize "+width+" "+height+" optimalSize pic " + optimalPicSize.width + " " + optimalPicSize.height + " pre " + optimalPreSize.width + " " + optimalPreSize.height);
            parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height);
            parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height);
            mProfile.videoFrameWidth = optimalPreSize.width;
            mProfile.videoFrameHeight = optimalPreSize.height;
            mProfile.videoBitRate = 5000000;//此参数主要决定视频拍出大小
        }
        mCamera.setParameters(parameters);
    }

    /** * 释放摄像头 */
    public void closeCamera() {
        if (mCamera != null) {
            try {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            } catch (Exception e) {
                LogUtils.i(e);
                if (mCamera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    /** * 集合不为空 * * @param list * @param <E> * @return */
    private <E> boolean isEmpty(List<E> list) {
        return list == null || list.isEmpty();
    }

    /** * 获取最佳预览相机Size参数 * * @return */
    private Camera.Size getOptimalSize(List<Camera.Size> sizes, int w, int h) {
        Camera.Size optimalSize = null;
        float targetRadio = h / (float) w;
        float optimalDif = Float.MAX_VALUE; //最匹配的比例
        int optimalMaxDif = Integer.MAX_VALUE;//最优的最大值差距
        for (Camera.Size size : sizes) {
            float newOptimal = size.width / (float) size.height;
            float newDiff = Math.abs(newOptimal - targetRadio);
            if (newDiff < optimalDif) { //更好的尺寸
                optimalDif = newDiff;
                optimalSize = size;
                optimalMaxDif = Math.abs(h - size.width);
            } else if (newDiff == optimalDif) {//更好的尺寸
                int newOptimalMaxDif = Math.abs(h - size.width);
                if (newOptimalMaxDif < optimalMaxDif) {
                    optimalDif = newDiff;
                    optimalSize = size;
                    optimalMaxDif = newOptimalMaxDif;
                }
            }
        }
        return optimalSize;
    }

    /** * 缩放 * @param isZoomIn */
    public void handleZoom(boolean isZoomIn) {
        if (mCamera == null) return;
        Camera.Parameters params = mCamera.getParameters();
        if (params == null) return;
        if (params.isZoomSupported()) {
            int maxZoom = params.getMaxZoom();
            int zoom = params.getZoom();
            if (isZoomIn && zoom < maxZoom) {
                zoom++;
            } else if (zoom > 0) {
                zoom--;
            }
            params.setZoom(zoom);
            mCamera.setParameters(params);
        } else {
            LogUtils.i("zoom not supported");
        }
    }

    /** * 更换前后置摄像 */
    public void changeCameraFacing(SurfaceTexture surfaceTexture, int width, int height) {
        if(isSupportFrontCamera) {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            int cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数
            for(int i = 0; i < cameraCount; i++) {
                Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
                if(cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //现在是后置,变更为前置
                    if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位为前置
                        closeCamera();
                        cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
                        CameraUtils.setCameraFacing(context, cameraFacing);
                        openCamera(surfaceTexture, width, height);
                        break;
                    }
                } else {//现在是前置, 变更为后置
                    if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位
                        closeCamera();
                        cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
                        CameraUtils.setCameraFacing(context, cameraFacing);
                        openCamera(surfaceTexture, width, height);
                        break;
                    }
                }
            }
        } else { //不支持摄像机
            Toast.makeText(context, "您的手机不支持前置摄像", Toast.LENGTH_SHORT).show();
        }
    }

    /** * 改变闪光状态 */
    public void changeCameraFlash(SurfaceTexture surfaceTexture, int width, int height) {
        if (!isSupportFlashCamera) {
            Toast.makeText(context, "您的手机不支闪光", Toast.LENGTH_SHORT).show();
            return;
        }
        if(mCamera != null) {
            Camera.Parameters parameters = mCamera.getParameters();
            if(parameters != null) {
                int newState = cameraFlash;
                switch (cameraFlash) {
                    case 0: //自动
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        newState = 1;
                        break;
                    case 1://open
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        newState = 2;
                        break;
                    case 2: //close
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                        newState = 0;
                        break;
                }
                cameraFlash = newState;
                CameraUtils.setCameraFlash(context, newState);
                mCamera.setParameters(parameters);
            }
        }
    }

    /** * 拍照 */
    public void takePhoto(Camera.PictureCallback callback) {
        if (mCamera != null) {
            try {
                mCamera.takePicture(null, null, callback);
            } catch(Exception e) {
                Toast.makeText(context, "拍摄失败", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /** * 开始录制视频 */
    public void startMediaRecord(String savePath) {
        if (mCamera == null || mProfile == null) return;
        mCamera.unlock();
        if (mMediaRecorder == null) {
            mMediaRecorder = new MediaRecorder();
            mMediaRecorder.setOrientationHint(90);
        }
        if (isCameraFrontFacing()) {
            mMediaRecorder.setOrientationHint(270);
        }
        mMediaRecorder.reset();
        mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        mMediaRecorder.setProfile(mProfile);
        mMediaRecorder.setOutputFile(savePath);
        try {
            mMediaRecorder.prepare();
            mMediaRecorder.start();
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    /** * 停止录制 */
    public void stopMediaRecord() {
        stopRecorder();
        releaseMediaRecorder();
    }

    private void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            try {
                mMediaRecorder.reset();
                mMediaRecorder.release();
                mMediaRecorder = null;
                mCamera.lock();
            } catch (Exception e) {
                e.printStackTrace();
                LogUtils.i(e);
            }
        }
    }

    private void stopRecorder() {
        if (mMediaRecorder != null) {
            try {
                mMediaRecorder.stop();
            } catch (Exception e) {
                e.printStackTrace();
                LogUtils.i(e);
            }

        }
    }

    public boolean isSupportFrontCamera() {
        return isSupportFrontCamera;
    }

    public boolean isSupportFlashCamera() {
        return isSupportFlashCamera;
    }

    public boolean isCameraFrontFacing() {
        return cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT;
    }

    public void setCameraType(int cameraType) {
        this.cameraType = cameraType;
    }

    public int getCameraFlash() {
        return cameraFlash;
    }

    /** * 对焦 * @param x * @param y */
    public void handleFocusMetering(float x, float y) {
        Camera.Parameters params = mCamera.getParameters();
        Camera.Size previewSize = params.getPreviewSize();
        Rect focusRect = calculateTapArea(x, y, 1f, previewSize);
        Rect meteringRect = calculateTapArea(x, y, 1.5f, previewSize);
        mCamera.cancelAutoFocus();

        if (params.getMaxNumFocusAreas() > 0) {
            List<Camera.Area> focusAreas = new ArrayList<>();
            focusAreas.add(new Camera.Area(focusRect, 1000));
            params.setFocusAreas(focusAreas);
        } else {
            LogUtils.i("focus areas not supported");
        }
        if (params.getMaxNumMeteringAreas() > 0) {
            List<Camera.Area> meteringAreas = new ArrayList<>();
            meteringAreas.add(new Camera.Area(meteringRect, 1000));
            params.setMeteringAreas(meteringAreas);
        } else {
            LogUtils.i("metering areas not supported");
        }
        final String currentFocusMode = params.getFocusMode();
        params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.setParameters(params);

        mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                Camera.Parameters params = camera.getParameters();
                params.setFocusMode(currentFocusMode);
                camera.setParameters(params);
            }
        });
    }

    private Rect calculateTapArea(float x, float y, float coefficient, Camera.Size previewSize) {
        float focusAreaSize = 300;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();
        int centerX = (int) (x / previewSize.width - 1000);
        int centerY = (int) (y / previewSize.height - 1000);
        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);
        RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
        return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom));
    }

    private int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

}

5:最后是CameraActivity中的代码,这里贴上拍摄视频进度控制代码

mProgressbar.setOnProgressTouchListener(new CameraProgressBar.OnProgressTouchListener() {
            @Override
            public void onClick(CameraProgressBar progressBar) {
            }

            @Override
            public void onLongClick(CameraProgressBar progressBar) {
                rl_camera.setVisibility(View.GONE);
                recorderPath = FileUtils.getUploadVideoFile(mContext);
                cameraManager.startMediaRecord(recorderPath);
                isRecording = true;
                progressSubscription = Observable.interval(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()).take(max).subscribe(new Subscriber<Long>() {
                    @Override
                    public void onCompleted() {
                        stopRecorder(true);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onNext(Long aLong) {
                        mProgressbar.setProgress(mProgressbar.getProgress() + 1);
                    }
                });
            }

            @Override
            public void onZoom(boolean zoom) {
                cameraManager.handleZoom(zoom);
            }

            @Override
            public void onLongClickUp(CameraProgressBar progressBar) {
                stopRecorder(true);
                if (progressSubscription != null) {
                    progressSubscription.unsubscribe();
                }
            }

            @Override
            public void onPointerDown(float rawX, float rawY) {
                if (mTextureView != null) {
                    mCameraView.setFoucsPoint(new PointF(rawX, rawY));
                }
            }
        });

        mCameraView.setOnViewTouchListener(new CameraView.OnViewTouchListener() {
            @Override
            public void handleFocus(float x, float y) {
                cameraManager.handleFocusMetering(x, y);
            }

            @Override
            public void handleZoom(boolean zoom) {
                cameraManager.handleZoom(zoom);
            }
        });
        ViewClickOnSubscribe clickOnSubscribe = new ViewClickOnSubscribe();
        clickOnSubscribe.addOnClickListener(mProgressbar);
        clickSubscription = Observable.create(clickOnSubscribe).throttleFirst(1000 , TimeUnit.MILLISECONDS ).subscribe(new Action1<View>() {
            @Override
            public void call(View view) {
                switch (view.getId()) {
                    case R.id.mProgressbar:
                        cameraManager.takePhoto(callback);
                        break;
                }
            }
        });


/** * camera回调监听 */
    private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
            if (recorderPath != null) {
                iv_choice.setVisibility(View.VISIBLE);
                setTakeButtonShow(false);
                playerManager.playMedia(new Surface(texture), recorderPath);
            } else {
                setTakeButtonShow(true);
                iv_choice.setVisibility(View.GONE);
                cameraManager.openCamera(texture, width, height);
            }
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture texture) {
        }
    };

小结:拍照功能涉及到系统权限,在6.0或以上的版本中要申请权限, 也可以修改targetSdkVersion 22(或以下),如果rxjava不懂的可以先去了解下rxjava)
权限

没有做横竖切屏的效果,有需要的可以自己去加
上班时间到了,如果有错误的地方欢迎多多指点,谢谢 !!!

最后附上源码地址:download.csdn.net/detail/u012…

    原文作者:Android
    原文地址: https://juejin.im/entry/58df27000ce4630058225f20
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞