二维码扫描的手势调焦

最近在zxing二维码扫描的功能基础上 添加相机的手势调焦 遇到个坑 特此记录

参考了这篇博客http://blog.csdn.net/qq_24531461/article/details/62887658

二指手势缩放

这个听起来很难,但实际很容易。首先消除一个误解,当对相机进行缩放时,无论手指是在屏幕哪个地方缩放,实际都是以预览的中心进行缩放,因为缩放时相机的角度是没有变的。所以我们只需要知道用户两只手指是在放大还是缩小,然后通过setZoom()指定缩放程度,应用到相机就好了。

手指间距

注意不同于触摸对焦,现在我们只需要知道手指是合拢还是张开,不需要知道手指的具体位置。怎么知道手指是合拢还是张开?可惜android并没有提供这个方法,只会告诉我们有两个手指,还告诉手指的坐标;我们可以记下手指之间的间距,如果在手指移动时间距变大,那就是张开,否则就是合拢。

首先是计算手指间距,在CameraPreview中加入

Java
private static float getFingerSpacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return (float) Math.sqrt(x * x + y * y);
}

MotionEvent中获取两个手指的坐标(提前保证一定有两个手指),然后计算距离,很简单。

设置缩放

判断手指合拢还是张开稍后再说,现在来看在知道是合拢还是张开后,怎么设置缩放。

对于相机来说,缩放程度是介于[0, getMaxZoom()]之间的,不缩放时值为0,具体数值通过setZoom()设置,应用到相机就能看到效果了。所以只需要在每次触发设置缩放时,根据是缩小还是放大,将缩放值减1或加1,并应用到相机。对于一次缩放手势,会多次触发设置缩放,这样就形成了一个连续的缩放过程,看起来就像过渡效果了。

CameraPreview中加入

Java
private void handleZoom(boolean isZoomIn, Camera camera) {
    Camera.Parameters params = camera.getParameters();
    if (params.isZoomSupported()) {
        int maxZoom = params.getMaxZoom();
        int zoom = params.getZoom();
        if (isZoomIn && zoom < maxZoom) {
            zoom++;
        } else if (zoom > 0) {
            zoom--;
        }
        params.setZoom(zoom);
        camera.setParameters(params);
    } else {
        Log.i(TAG, "zoom not supported");
    }
}

isZoomSupported()判断相机是否支持缩放,不支持就不用瞎折腾了。getMaxZoom()获取最大缩放值,最小值为0不用获取;getZoom()获取当前缩放值,如果是放大,且当前缩放值不超过最大值,则将当前缩放值加1;如果是缩小,且当前缩放值不小于0,则将当前缩放值减1。最后应用到相机,就完成了整个过程。

捕获二指缩放

先看代码,在CameraPreview中加入

Java
private float oldDist = 1f;

并将onTouchEvent()修改为

Java
public boolean onTouchEvent(MotionEvent event) {
     if (event.getPointerCount() == 1) {
         handleFocus(event, mCamera);
     } else {
         switch (event.getAction() & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_POINTER_DOWN:
                 oldDist = getFingerSpacing(event);
                 break;
             case MotionEvent.ACTION_MOVE:
                 float newDist = getFingerSpacing(event);
                 if (newDist > oldDist) {
                     handleZoom(true, mCamera);
                 } else if (newDist < oldDist) {
                     handleZoom(false, mCamera);
                 }
                 oldDist = newDist;
                 break;
         }
     }
     return true;
 }

我们只看两指手势的部分。event.getAction() & MotionEvent.ACTION_MASK获取手势类别;ACTION_POINTER_DOWN即为两只手指触摸到屏幕,此时我们通过两只手指的坐标得到手指间距,记录到成员变量oldDist中;ACTION_MOVE即为手指在屏幕上移动,对应两只手指正在缩放,缩放过程中每次手指移动都会触发。此时记录新的手指间距为newDist,并与oldDist比较,确定缩放类型,调用handleZoom()进行缩放;相机缩放完成后,将oldDist赋值为newDist,作为下一次触发ACTION_MOVE的基准,这样完成缩放。


整体的思路没有问题 也能够实现 最大的一个坑就是 在自定义的surfaceview中 的camera是应该和 之前初始化的camera保持一致的 

如果不一致那么 就会导致画面卡死 camera.autofocus 失败的错误

解决办法 在CameraManager类中  写一个方法 return camera  在自定义的surfaceview中接收   同时要判断好  !null 

现在手势调焦反应有点慢 还有待于优化一下。。。


优化完成  你只要把放大缩小的zoom++  zoom--  改成 zoom=zoom+6   zoom = zoom-6  这样每次增加的不是1 而是6 那么缩放的速度就快了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值