android仿微信錄製短視訊,拍照,自動聚焦,手動聚焦,滑動縮放功能(Camera+TextureView+rxjava實現)
阿新 • • 發佈:2019-02-05
1:需求分析
先上圖看效果
a:拍照時,中間的拍照按鈕稍微小些,單擊可以拍照,長按時中間的拍照按鈕變大,並有進度提示拍攝視訊進度
b:中間區域可以手勢縮放,單擊時可以根據該點進行拍攝/拍照對焦,介面上顯示對焦動畫
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)
許可權
沒有做橫豎切屏的效果,有需要的可以自己去加
上班時間到了,如果有錯誤的地方歡迎多多指點,謝謝 !!!