经过上一篇 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一下不亏.