放大镜就是直接调用相机,使用放大缩小的功能实现,调用相机有两种方式,一种是直接调用系统的;另一种是自定义相机,需要自定义一个预览界面,下面简单介绍自定义相机方式:
参考:http://developer.android.com/guide/topics/media/camera.html
首先我们需要申请权限:
1、获取需要的权限,检测手机是否有相机。
//manifest里添加使用相机的权限
<uses-permission android:name="android.permission.CAMERA" />
//使用相机属性
<uses-feature android:name="android.hardware.camera" />
//相机自动对焦
<uses-feature android:name="android.hardware.camera.autofocus" />
然后再判断是否有相机存在:
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
2.打开相机,官网实现的安全方式打开相机
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
3、创建预览窗口,这是最主要的部分
SurfaceView:该类是一个视图组件,实现了照片的预览功能。
SurfaceHolder:一个抽象接口,是SurfaceView的支持类,一般通过SurfaceView的getHolder()方法获得。允许你控制界面的尺寸和格式、编辑界面的像素,以及监控界面尺寸的改变。
SurfaceHolder.Callback:SurfaceHolder 的一个内部接口,可以实现该接口获取界面改变的信息。该接口中有三个方法,surfaceCreated()方法在界面创建时被调用,一般在该方法中打开 照相机并设置预览。surfaceChanged()方法在界面尺寸改变时 被调用,一般在该方法中设置相机的参数(大小、格式等)。 surfaceDestroyed()方法在界面被销毁时调用,在该方法中清除相机实例,释放资源。
Camera:相机类,实现拍照功能。
Camera.PictureCallback:Camera的一个内部接口,处理照片准备好后的回调。
接着我们定义预览窗口的自定义View
/** A basic Camera preview class */
public class MyPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public MyPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
//获取相机属性
Camera.Parameters parameters = mCamera.getParameters();
//自动对焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
//由于相机默认是横屏的,创建时旋转一下调正位置
if(this.getResources().getConfiguration().orientation!= Configuration.ORIENTATION_LANDSCAPE){
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
parameters.setRotation(90);
}else{
parameters.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
parameters.setRotation(0);
}
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// return super.onTouchEvent(event);
//按下时自动对焦
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCamera.autoFocus(null);
}
return true;
}
}
4、添加seekbar调节预览区域的缩放。
由于在Nexus5上获取到的maxZoom是99,如果你的设备取不到这么大,那么需要将progress的刻度乘一个比例,以免报错。
/**
* maxZoom = parameters.getMaxZoom(); 最大缩放
* ratio = 100 / maxZoom;获取比例
*/
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
Camera c = mCamera;
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(progress / ratio < maxZoom)
parameters.setZoom(progress / ratio);
c.setParameters(parameters);
c.autoFocus(null);
}
下面是Demo的核心部分代码:
public class MainActivity extends Activity {
private Camera mCamera;
private CameraPreview mPreview;
private boolean isClicked = false;
private Camera.AutoFocusCallback mAutoFocusCallback;
private SeekBar seekBar;
private int maxZoom;
private int ratio = 1;
Camera.Parameters parameters;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
seekBar = (SeekBar)findViewById(R.id.seekBar);
mCamera = safeCameraOpen();
mAutoFocusCallback = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
Camera c=mCamera;
// TODO Auto-generated method stub
if(success){
//自动对焦成功
c.setOneShotPreviewCallback(null);
}
};
if(mCamera != null) {
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.framelayout);
preview.addView(mPreview);
parameters = mCamera.getParameters();
maxZoom = parameters.getMaxZoom();
if(maxZoom > 0)
ratio = 100 / maxZoom;
// parameters.setZoom(99);
// mCamera.setParameters(parameters);
}
/**
* maxZoom = parameters.getMaxZoom(); 最大缩放
* ratio = 100 / maxZoom;获取比例
*/
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
Camera c = mCamera;
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(progress / ratio < maxZoom)
parameters.setZoom(progress / ratio);
c.setParameters(parameters);
c.autoFocus(null);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
protected void onPause() {
super.onPause();
if(mCamera != null){
mCamera.release();
}
}
@Override
protected void onResume(){
super.onResume();
mCamera = safeCameraOpen();
}
//camera
private Camera safeCameraOpen() {
Camera c = null;
try {
c = Camera.open();
} catch (Exception e) {
Log.e(getString(R.string.app_name), "failed to open Camera");
e.printStackTrace();
}
return c;
}
//自定义相机展览区
public class MyPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public MyPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
//获取相机属性
Camera.Parameters parameters = mCamera.getParameters();
//自动对焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
//由于相机默认是横屏的,创建时旋转一下调正位置
if(this.getResources().getConfiguration().orientation!= Configuration.ORIENTATION_LANDSCAPE){
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
parameters.setRotation(90);
}else{
parameters.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
parameters.setRotation(0);
}
mCamera.setParameters(parameters);
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// make any resize, rotate or reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
e.printStackTrace();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// return super.onTouchEvent(event);
//按下时自动对焦
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCamera.autoFocus(null);
}
return true;
}
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
}