Android 放大镜效果实现

放大镜就是直接调用相机,使用放大缩小的功能实现,调用相机有两种方式,一种是直接调用系统的;另一种是自定义相机,需要自定义一个预览界面,下面简单介绍自定义相机方式:
参考: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;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值