Android Camera Develop: touch to focus, touch to metering, double finger touch to zoom

概述

本篇在(四)的基础上继续对相机APP的功能进行增强。触摸对焦,就是在屏幕上点击某个点,相机就以此点内容进行对焦,保证此点最清晰;触摸测光,就是在屏幕上点击某个点,相机调整曝光亮度,保证此点亮度最为合适;二指手势缩放,就是通过手指在屏幕上的缩放,相机内容也随之进行缩放。上述三个功能也是目前相机APP较为常见的功能,我们接下来就进行实现。

触摸对焦

你要是仔细看过Camera.Parameters的官方文档的话,大概见过setFocusAreas()方法,就像字面意思一样,这个方法就是用来指定对焦区域的,而触摸对焦主要就是依靠这个方法实现。通过监听相机预览的触摸事件,获得手指触摸屏幕的坐标,然后通过setFocusAreas()指定这个对焦区域,最后应用到相机就好了。

坐标转换

手指触摸屏幕的坐标并不能直接应用于setFocusAreas(),因为相机会用到另一套坐标系,如下图所示(来自官方文档)

相机预览中心是(0, 0),左上角是(-1000, -1000),右下角是(1000, 1000)。其中蓝色的矩形就是一个对焦区域,相机以此区域进行对焦。这个坐标系可以让我们免于实际尺寸的困扰,还有一个好处就是这个坐标系不会受预览内容的旋转的影响,就是说只需要做一次坐标变换就好了。

在CameraPreview中加入

calculateTapArea()接收触摸点的坐标,返回转换后坐标介于[-1000, 1000]矩形。这是一个较为通用的代码,应该很容易看懂。

感谢评论区【11】同学的对calculateTapArea()方法中的错误的指正!

设置对焦区域

在得到转换后的矩形后就可以直接通过setFocusAreas()应用到相机了?实际没这么简单。直接这么做往往不能达到理想的效果,因为Android本身的问题以及设备的差异,在常用的对焦模式为continuous-picture下,setFocusAreas()可能会不工作。目前常用的解决办法是在setFocusAreas()同时修改相机对焦模式为macro等,待对焦完毕后,再将对焦模式修改为用户之前定义的。

在CameraPreview中加入

前面大部分是设置曝光区域,很容易,getMaxNumFocusAreas()用来判断相机是否支持设定手动对焦点,如果不支持就不用瞎折腾了;cancelAutoFocus()是将相机的所以对焦完成后的回调函数都去掉,其实无关紧要。currentFocusMode就是保存用户设置的对焦方式,然后将对焦方式修改为macro,应用到相机,相机开始对焦。什么时候把对焦方式还原为用户设定的呢?当然是在相机对焦完成后,我们通过autoFocus()设定一个回调函数,当相机对焦完成后就会调用这个回调函数,我们就可以在回调函数里设置将对焦方式修改回用户设定的,然后应用到相机。

捕获触摸事件

SurfaceView就有onTouchEvent()触摸事件,我们只需要将其重载实现自己想要的功能就好了。

在CameraPreview中加入

getPointerCount获取手指数目,当只有一个手指时触发对焦,直接调用handleFocus()就好了。

运行试试

现在APP就实现了触摸对焦了,运行试试吧。如下面两图就是分别以两本书的内容进行对焦,可以明显发现一本清晰一本模糊。

触摸测光

触摸测光与触摸对焦大同小异,一般来说我们希望在以指定点对焦的同时也以此点测光,调节亮度,只需要修改handleFocus()就好了。

在handleFocus()中加入

getMaxNumMeteringAreas()用来判断相机是否支持设定手动测光点,如果不支持就不用瞎折腾了。在DEMO中handleFocus()的名字变为handleFocusMetering()了,因为现在不止能够进行对焦了嘛。

运行试试

现在触摸屏幕会同时完成对焦和测光,运行试试吧。

二指手势缩放

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

手指间距

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

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

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

设置缩放

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

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

在CameraPreview中加入

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

捕获二指缩放

先看代码,在CameraPreview中加入

并将onTouchEvent()修改为

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

运行试试

现在在屏幕上用手指进行缩放,就会使相机预览缩放了,运行试试吧。如下面两图就是缩放前和缩放后

一点唠叨

上面我们实现了触摸对焦,触摸测光,二指手势缩放,看起来比较简单但也还是有许多细节问题值得深入探究。本篇美中不足的就是没有给触摸和手势加上动画,比如触摸时应该在屏幕上显示一个矩形指示,缩放时应该在屏幕上显示一个进度条指示缩放程度;鉴于加上这些内容需要更多代码和一些技巧,本篇没有实现,望自行查找(参考部分有个链接涉及到这个问题)。另外对于这些功能的实现也可以有不同的策略,我只是提出我认为最合适的方法,可能不是最好的。

DEMO

参考

android触屏对焦_Android相机开发(五): 触摸对焦,触摸测光,二指手势缩放相关推荐

  1. Android相机开发: 触摸对焦,触摸测光,二指手势缩放

    转自此处 概述 本篇在(四)的基础上继续对相机APP的功能进行增强.触摸对焦,就是在屏幕上点击某个点,相机就以此点内容进行对焦,保证此点最清晰:触摸测光,就是在屏幕上点击某个点,相机调整曝光亮度,保证 ...

  2. android 代码功能测试,Android触屏测试实例代码

    本文实例详细描述了Android触屏测试代码,可实现对触屏的点击.移动.离开等事件的处理,对于Android初学者有很好的借鉴价值. 具体功能代码如下: package com.test; impor ...

  3. android 触摸 事件,Android触屏事件和MotionEvent详解

    Android屏幕操作 屏幕是用户和Android设备交互的主要媒介,屏幕分为触屏和非触屏.Android设备目前有四种类型:Android Phone,Android Tablet,Android ...

  4. android 触摸时震动,android触屏震动以及震动强度批改

    android触屏震动以及震动强度修改 PhoneWindowManager.java: 在interceptKeyBeforeQueueing函数中 performHapticFeedbackLw( ...

  5. android分屏模式_Android分屏模式开发注意事项

    Android分屏模式开发注意到主页面在分屏模式下,页面所占比例在增大或者减小的时候都会调用oncreat方法,所以查资料总结一下分屏对页面的生命周期的影响以及开发时的注意事项: App页面从全屏模式 ...

  6. [Android] 触屏setOnTouchListener实现图片缩放、移动、绘制和添加水印

        前一篇文章讲述了Android实现图片Matrix矩阵类缩放.旋转.对比度.亮度.饱和度处理,但是真正的图片软件都是使用触屏实现图片缩放.移动.添加水印等功能,所以该篇文章主要通过setOnT ...

  7. android触屏设备event模拟,android 使用命令模拟点击 滑动

    adb shell getevent -p 出现上述截图的就是屏幕触摸输入设备 带上 -l adb shell getevent -p-l . EV_ABS      ABS_MT_TRACKING_ ...

  8. android 截屏函数_android截屏功能实现代码

    这篇文章主要为大家详细介绍了android截屏功能的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 android开发中通过View的getDrawingCache方法可以达到截屏的目的, ...

  9. android触屏压力方案,触摸屏实现原理与在android上实现.doc

    PAGE 6 武汉工程大学邮电与信息工程学院毕业设计(论文) 武汉工程大学邮电与信息工程学院 毕业设计(论文) 触摸屏的实现原理及在android上的实现 The Principle of the T ...

最新文章

  1. 人脸真伪验证与识别:ICCV2019论文解析
  2. Android Training - Volley(Lesson 0 - 序言)
  3. springmvc请求参数获取(自动绑定)的几种方法
  4. python比较两个数的和_Python中的is和==比较两个对象的两种方法
  5. 边打工边研究数学 泸州“农民数学家”出版15本著作
  6. php用json_encode编码后乱码,php json_encode()函数中文编码乱码解决方法_PHP教程
  7. 制备pdms膜的方法_船体用钢板基底超疏水表面的制备和性能
  8. win下anaconda装python2.7和3.5以及jupyter共存 (本篇实践通过)
  9. mac android mtp,果粉也用安卓!MacBook连接安卓机最好的工具
  10. 消息称经销商10月5日将拿到iPhone 12
  11. nuxt服务端php,nuxt服务端部署上线
  12. mybatis 大量insert 出现sql io 异常_Java自学之mybatis:使用注解方式实现CURD
  13. ubuntu linux 系统搭建我的世界基岩版 私服我的世界服务器
  14. 安卓开源电子书 阅读器_4个适用于Android的开源电子书阅读器
  15. 阿拉伯数字 - 书法
  16. 吃货必看!全新技术告诉我们未来吃什么
  17. 如何把illustrator圆圈5等分?
  18. 07-PDI(Kettle)源码编译8.2.0.0.R版本
  19. 如何解决您与此网站之间建立的连接不安全,该页面采用不加密的http传输协议?
  20. python中的计时模块:time.time()

热门文章

  1. 融创年报再获佳绩,“地产+”业务快速崛起,融创天花板在哪里?
  2. [WDS]Disconnected!
  3. android通知小图标灰色,android – 大型通知图标旁边的灰色圆圈?
  4. [低级错误]an attribute defined in * line * hides this method pylint (method-hidden)
  5. c#精华网站收集(转摘自梅川酷子的博客)
  6. 布尔逻辑析取范式思考
  7. STM32在线烧录程序的开发
  8. Android 自定义View
  9. GFPGAN:老旧照片的面部恢复神器
  10. 【21.00%】【vijos P1018】智破连环阵