想搞自定义相机很久了一直觉得很难所以一直拖着前两天有点闲就参考Android自定义相机超详细讲解搞了一下发现并不是那么难,嘿嘿~
一、参考布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/diy_camera_fy_context"
android:layout_width="match_parent"
android:layout_height="match_parent"
>FrameLayout>
<LinearLayout
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/diy_camera_btn_pat"
android:text="拍照"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<Button
android:id="@+id/diy_camera_btn_exchange_camera"
android:text="切换摄像头"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
<Button
android:id="@+id/diy_camera_btn_open_flashlight"
android:text="打开闪光灯"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content" />
LinearLayout>
RelativeLayout>
二、初始化相机
/**
* 获取照相机实例
*
* @return
*/
private Camera getCamera() {
Camera camera = null;
if (CameraProvider.hasCamera()) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD) {
//打开摄像头
camera = Camera.open();
} else {
//打开摄像头
camera = Camera.open(cameraType);
}
} else {
ToastUtils.showShort("摄像头打开失败");
}
return camera;
}
这里需要说明一下:
/**
* 初始化相机
*/
private void initCamera() {
mCamera = getCamera();
if (mCamera != null) {
pictureSizes.clear();
previewSizes.clear();
pictureSizes = mCamera.getParameters().getSupportedPictureSizes();
previewSizes = mCamera.getParameters().getSupportedPreviewSizes();
//得到摄像头的参数
parameters = mCamera.getParameters();
parameters.setJpegQuality(80);//设置照片的质量
parameters.setPreviewSize(previewSizes.get(0).width, previewSizes.get(0).height);//设置预览尺寸
parameters.setPictureSize(pictureSizes.get(0).width, pictureSizes.get(0).height);//设置照片分辨率
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);// 连续对焦模式
parameters.setFlashMode(flashMode);
//Camera.Parameters.FOCUS_MODE_AUTO; //自动聚焦模式
//Camera.Parameters.FOCUS_MODE_INFINITY;//无穷远
//Camera.Parameters.FOCUS_MODE_MACRO;//微距
//Camera.Parameters.FOCUS_MODE_FIXED;//固定焦距
parameters.setRotation(90); //生成的图像旋转90度
mCamera.setParameters(parameters);
isPreviewing = true;
//设置摄像头角度
setCameraDisplayOrientation(CustomCameraActivity.this, 0, mCamera);
} else {
ToastUtils.showShort("摄像头打开失败");
}
}
/**
* 设置 摄像头的角度
*
* @param activity 上下文
* @param cameraId 摄像头ID(假如手机有N个摄像头,cameraId 的值 就是 0 ~ N-1)
* @param camera 摄像头对象
*/
public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) {
Camera.CameraInfo info = new Camera.CameraInfo();
//获取摄像头信息
Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
//获取摄像头当前的角度
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
// 前置摄像头
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else {
// 后置摄像头
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private Camera mCamera ;
private SurfaceHolder mHolder;
public CameraPreview(Context context,Camera camera) {
super(context);
mCamera = camera;
//获取SurfaceHolder
mHolder = getHolder();
//为SurfaceHolder设置回调
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// 当Surface被创建之后,开始Camera的预览
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "预览失败");
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Surface发生改变的时候将被调用,第一次显示到界面的时候也会被调用
if (mHolder.getSurface() == null){
// 如果Surface为空,不继续操作
return;
}
// 停止Camera的预览
try {
mCamera.stopPreview();
} catch (Exception e){
Log.d(TAG, "当Surface改变后,停止预览出错");
}
// 重新开始预览
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "预览Camera出错");
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
cameraPreview = new CameraPreview(mContext, mCamera);
diyCameraFyContext.addView(cameraPreview);
mCamera.takePicture(null, null, (data, camera) -> {
Bitmap mbitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
});
Camera.open( Camera.CameraInfo.CAMERA_FACING_FRONT/CAMERA_FACING_BACK);
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH / FLASH_MODE_OFF);
mCamera.cancelAutoFocus();
//恢复对焦模式
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
parameters.setFocusAreas(null);
mCamera.setParameters(parameters);
mCamera.startPreview();
@Override
protected void onDestroy() {
super.onDestroy();
// 回收Camera资源
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
@Override
protected void onResume() {
super.onResume();
if (mCamera != null) {
mCamera.startPreview();
}
}
@Override
public void onStop() {
super.onStop();
if (mCamera != null) {
mCamera.stopPreview();
}
}
/**
* 停止销毁摄像机
*/
private void stopCamera() {
if (mCamera != null) {
//停止当前摄像头预览
mCamera.stopPreview();
//释放摄像机资源
mCamera.release();
mCamera = null;
}
}
Github:https://github.com/distantplace-z/BaseTools/blob/master/sample/src/main/java/com/xiaohou/sample/ui/camera/CustomCameraActivity.java
温馨提示:
此文章是基于Camera的在Android SDK 21(LOLLIPOP)以后已经弃用Camera了开始使用Camera2但是那么问题来了我们需不需要根据Android SDK来写对应版本的Camera呢?答案是要滴但是呢有个好消息就是Google出了cameraview解决了我们一大部分问题,但是Camera2是一个很强大的库具体有多强大待博主一探究竟…