前段时间在做face++相关的功能,对于照相机也是进行了一番研究,小有收获,很感谢有一些大神已经写了相应的博客,让我在他们的项目上进行完善和优化,修复了一些bug,并对机型适配做了一些处理,目前已经保证了团队里面十多部安卓手机的完美适配,具体项目资源可以在http://download.csdn.net/detail/shan286/9799622这个网址上下载。好的,话不多说,直接上代码。
1、首先是关于照相机的预览功能,这里就要说到SurfaceView这个控件,我在布局最底层放了一个自定义的MySurfaceView,然后在它的上层放一个自定义的TakePhotoView,这个TakePhotoView主要是用于当用户想要在拍照的时候绘制自己想要的图片时,就可以在这个View中实现,这里我是画了一个带橙色框框的图片放在了里面。MySurfaceView的代码如下:
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by xueli on 2016/11/16.
*
* 1、注意点:surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁
* 2、实现过程:继承SurfaceView并实现SurfaceHolder.Callback接口
* ----> SurfaceView.getHolder()获得SurfaceHolder对象
* ----> SurfaceHolder.addCallback(callback)添加回调函数
* ----> SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
* ----> Canvas绘画
* ----> SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
*/
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "MySurfaceView";
private Context mContext;
private SurfaceHolder mSurfaceHolder;
public MySurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mSurfaceHolder = getHolder();
mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//在创建时激发,一般在这里调用画图的线程。
Log.i(TAG, "surfaceCreated...");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//在surface的大小发生改变时激发
Log.i(TAG, "surfaceChanged...");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//销毁时激发,一般在这里将画图的线程停止、释放。
Log.i(TAG, "surfaceDestroyed...");
CameraInterface.getInstance().doStopCamera();
}
public SurfaceHolder getSurfaceHolder() {
// SurfaceHolder当作surface的控制器,用来操纵surface
return mSurfaceHolder;
}
}
TakePhotoView的代码如下:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import com.sherry.ui.R;
import com.sherry.util.DeviceInfoUtil;
/**
* Created by xueli on 2016/11/16.
*
* 自定义拍照框View
*
*/
public class TakePhotoView extends View {
private Context mContext;
private Paint mPaint;
public TakePhotoView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
mPaint = new Paint();
mPaint.setAntiAlias(false);
}
@Override
protected void onDraw(Canvas canvas) {
// 拍照框预览的宽高设置
Rect frame = new Rect(0, 0, DeviceInfoUtil.getScreenWidth(mContext), DeviceInfoUtil.getScreenHeight(mContext) * 17 / 25);
mPaint.setColor(Color.GRAY);
Rect faceRect = new Rect();
faceRect.left = frame.left;
faceRect.right = frame.right;
faceRect.top = frame.top;
faceRect.bottom = frame.bottom;
canvas.drawBitmap(((BitmapDrawable) (getResources().getDrawable(R.drawable.take_photo_bg))).getBitmap(), null, faceRect, mPaint);
}
}
2、照相机处理类------CameraInterface
(1)在CameraInterface这个类里面对照相机进行一些处理,包括照相机的开启、预览、拍照、销毁等方法,这里参考博客http://blog.csdn.net/yanzi1225627/article/details/33028041,可以说给我提供了很大的帮助。不过我在它的实现上进行了优化和改进,解决了部分手机的黑屏、拍照或预览变形等问题。因为我这边要求的是拍照之后显示图片在下一个页面进行显示,所以拍照之后不会只是暂停然后继续进行预览,另外要注意的是,我这边使用的是前置摄像头,所以在doOpenCamera()方法中要判断手机摄像头的个数,让它选择开启前置摄像头。具体代码如下:
/**
* 打开Camera
*
* @param callback
*/
public void doOpenCamera(CamOpenOverCall