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() { @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 = https://www.it610.com/article/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 = https://www.it610.com/article/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 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 pictureSizes = parameters.getSupportedPictureSizes(); List 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 * @return */ private boolean isEmpty(List list) { return list == null || list.isEmpty(); }/** * 获取最佳预览相机Size参数 * * @return */ private Camera.Size getOptimalSize(List 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 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 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() { @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() { @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)
权限











没有做横竖切屏的效果,有需要的可以自己去加
上班时间到了,如果有错误的地方欢迎多多指点,谢谢 !!!
【android仿微信录制短视频,拍照,自动聚焦,手动聚焦,滑动缩放功能(Camera+TextureView+rxjava实现)】最后附上源码地址:http://download.csdn.net/detail/u012216274/9797226

    推荐阅读