博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 手把手带你玩转自定义相机
阅读量:4292 次
发布时间:2019-05-27

本文共 3306 字,大约阅读时间需要 11 分钟。

2016-10-26 一口仨馍
鸿洋
鸿洋

hongyangAndroid

你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。

本文由
一口仨馍投稿。

一口仨馍的博客地址:

http://blog.csdn.net/qq_17250009

作者将他多天的研究,完全的分享给了大家;再加上这篇文章撰写过程中也遇到了断电、文章被覆盖这样的事情,实属不易,非常感谢作者的分享。


1 概述   

相机几乎是每个APP都要用到的功能,万一老板让你定制相机方不方?反正我是有点方。关于相机的两天奋斗总结免费送给你。

Intent intent = new Intent();  intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);  startActivity(intent);

或者指定返回图片的名称mCurrentPhotoFile。

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(mCurrentPhotoFile));startActivityForResult(intent, CAMERA_WITH_DATA);

2 自定义启动相机   

今天以第二种为例。效果图如下 

自定义相机的一般步骤

  1. 创建显示相机画面的布局,Android已经为我们选定好SurfaceView

  2. 通过SurfaceView#getHolder()获得链接Camera和SurfaceView的SurfaceHolder

  3. Camame.open()打开相机

  4. 通过SurfaceHolder链接Camera和urfaceView

一般步骤的代码演示

添加相机和自动聚焦限权

将CameraSurfaceView放在布局文件中,这里建议最外层为FrameLayout,后面会用到。

如此,我们便有了一个没有照相功能的相机。初次之外,仔细观察相机显示画面,图片是不是变形严重?那是因为我们还没有为相机设置各种参数。在预览前要设置摄像头的分辨率、预览分辨率和图片分辨率的宽高比保持一致。这样图片才不会变形。这是个比较难以理解的部分,想深刻理解还需读者自己动手去实践

进去的是屏幕宽高,出来的是调整好了的参数。在surfaceChanged方法中执行mCamera.startPreview(); 前调用setCameraParams(mCamera, mScreenWidth, mScreenHeight); 就可以了。

最后要在AndroidManifest.xml里设置activity的方向:screenOrientation="portrait"代码里有很多注释,其中也有我自己调试时候的Log,大家可以自己调试下,看看不同参数的效果。昨天调参数搞到一点多,都在折腾这个函数。唉,一把辛酸泪。 

身为一个相机,居然不能照相?真是太丢脸了!

下面给我们的相机添加上照相的功能。照相核心代码就一句:mCamera.takePicture(null, null, jpeg); 

可以看到takePicture方法有三个参数,分别是ShutterCallback、PictureCallback和PictureCallback。这里我们只用了PictureCallback

在jpeg#onPictureTaken()里。我们将存储照片信息的byte[] data解析成bitmap,然后转换成JPG格式的图片保存在SD卡中。注意finally中最后两句mCamera.stopPreview();// 关闭预览 mCamera.startPreview();// 开启预览 上文也提到:当调用camera.takePiture()方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览。

如果不再次开启预览,则会一直停留在拍摄照片画面。为了方便外部调用拍照。这里我暴露了一个方法供外部拍照。

在布局文件中添加一个Button,点击Button执行takePicture()方法。不要忘了添加写SD卡限权

至此,一个具有照相并保存拍摄图片功能的相机就做出来了。

But,我们就此满足了吗?要是为了这些简单的功能我也不会写这篇博客。这只是个开始

3 真正的开始   

别人APP在照相的时候,屏幕上居然可以显示像效果图那样的框框啦、辅助点啦、图片bulabulabula~。在网上搜索一番实现方式,再加上一些自己的理解,构成了这篇博客。 

上文布局文件一直没有贴,现在贴出来大家先扫一眼,有些控件会在接下来展示

布局文件的最外层是个FrameLayout,我们知道FrameLayout是自带覆盖效果的。由来这个思路接下来就很简单了。编程重要的是思想,思想有了,其余的就剩具体的实现细节。

自定义边边框框

为了和CameraSurfaceView区分开,再自定义一个RectOnCamera专门用来画边边框框这些东西。这样做还一个好处是方便维护,不至于将所有东西都放在一个View中。

这里简单的画了一个类似二维码扫描的框框,还有一个类似聚焦的内外圆。

那么问题来了,聚焦的内外圆要随着手指滑而改变位置,而且要有聚焦的效果。可又和具有聚焦功能的CameraSurfaceView不是同一个类,不仅如此聚焦内外圆还完全覆盖了CameraSurfaceView。要处理这种问题,需要接口回调。这就是思想下面的细节。

现在虽然确定接口回调,但还有一个问题,CameraSurfaceView类和RectOnCamera类中都没有对方的对象或者引用。没错,通过共同持有RectOnCamera和CameraSurfaceView的Activity可以实现此功能。下面是具体的实现方法

动起来

首先,想要随着手指的滑动而改变RectOnCamera的位置肯定是要复写onTouchEvent()方法

其次,定义回调接口

在onTouchEvent()中return前加入

if (mIAutoFocus != null){      mIAutoFocus.autoFocus();  }

至此我们的回调接口已经定义好了,此时还需要CameraSurfaceView暴露一个聚焦方法,以便Activity调用

public void setAutoFocus(){    mCamera.autoFocus(this);}

准备工作已经全部完成,下面请看Activity的具体实现:

可以看到,MainActivity实现了IAutoFocus接口,并且在复写的IAutoFocus#autoFocus()方法中,调用了CameraSurfaceView暴露出来的方法setAutoFocus()。至此,在RectOnCamera每次的滑动过程中都会改变聚焦内外圆的位置,还会增加聚焦功能。一心二用甚至一心多用岂不是更好。

4

结束语

   

在经历两次断电没保存和一次CSDN服务器错误内容丢失之后终究还是完成了这篇博客,实属不易。十分感谢能听我啰嗦到结尾~

PS:Demo界面并没有做的很精致,只是提供了一种思路。按照此思路能做出比较华丽的效果,授人以鱼不如授人以渔。

源码下载

  • http://download.csdn.net/detail/qq_17250009/9484160


如果你有好的文章想和大家分享,欢迎投稿,直接向我投递文章链接即可。

欢迎长按下图->识别图中二维码或者扫一扫关注我的公众号:

http://download.csdn.net/detail/u011277123/9666549    示例下载地址
你可能感兴趣的文章
Sublime Text3插件详解
查看>>
netty源码分析之-ByteBuf详解(8)
查看>>
javascript函数定义三种方式详解
查看>>
javascript中this关键字详解
查看>>
javascript关于call与apply方法详解
查看>>
netty源码分析之-ReferenceCounted详解(9)
查看>>
javascript闭包详解
查看>>
javascript类的创建与实例对象
查看>>
javascript原型详解(1)
查看>>
netty源码分析之-处理器详解(9)
查看>>
javascript原型对象存在的问题(3)
查看>>
javascript原型继承(1)
查看>>
javascript原型继承-实现extjs底层继承(2)
查看>>
javascript设计模式-建立接口的方式(1)
查看>>
javascript设计模式-单体singleton模式(2)
查看>>
javascript设计模式-链式编程(3)
查看>>
大型高并发与高可用缓存架构总结
查看>>
javascript设计模式-工厂模式(4)
查看>>
javascript设计模式-组合模式(6)
查看>>
javascript设计模式-门面模式(7)
查看>>