Android 手把手带你玩转自定义相机
来源:互联网 发布:搜索方式的算法 编辑:程序博客网 时间:2024/04/30 03:45
http://blog.csdn.net/qq_17250009/article/details/52795530
版权声明:本文为博主原创文章,转载请征得博主同意并注明出处。
目录(?)[+]
- 概述
- 自定义相机的一般步骤
- 一般步骤的代码演示
- 真正的开始
- 自定义边边框框
- RectOnCamera
- 动起来
- 结束语
- 源码下载
概述
相机几乎是每个APP都要用到的功能,万一老板让你定制相机方不方?反正我是有点方。关于相机的两天奋斗总结免费送给你。
<code class="hljs avrasm has-numbering"> Intent intent = new Intent()<span class="hljs-comment">; </span> intent<span class="hljs-preprocessor">.setAction</span>(MediaStore<span class="hljs-preprocessor">.ACTION</span>_IMAGE_CAPTURE)<span class="hljs-comment">; </span> startActivity(intent)<span class="hljs-comment">;</span></code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets_01.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>
或者指定返回图片的名称mCurrentPhotoFile
。
<code class="hljs avrasm has-numbering"> Intent intent = new Intent(MediaStore<span class="hljs-preprocessor">.ACTION</span>_IMAGE_CAPTURE)<span class="hljs-comment">;</span> intent<span class="hljs-preprocessor">.putExtra</span>(MediaStore<span class="hljs-preprocessor">.EXTRA</span>_OUTPUT,Uri<span class="hljs-preprocessor">.fromFile</span>(mCurrentPhotoFile))<span class="hljs-comment">;</span> startActivityForResult(intent, CAMERA_WITH_DATA)<span class="hljs-comment">;</span></code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets_01.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>
2.自定义启动相机。
今天以第二种为例。效果图如下
自定义相机的一般步骤
- 创建显示相机画面的布局,
Android
已经为我们选定好SurfaceView
- 通过
SurfaceView#getHolder()
获得链接Camera
和SurfaceView
的SurfaceHolder
Camame.open()
打开相机- 通过
SurfaceHolder
链接Camera
和urfaceView
一般步骤的代码演示
<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CameraSurfaceView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">SurfaceView</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">SurfaceHolder</span>.<span class="hljs-title">Callback</span>, <span class="hljs-title">Camera</span>.<span class="hljs-title">AutoFocusCallback</span> {</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"CameraSurfaceView"</span>; <span class="hljs-keyword">private</span> Context mContext; <span class="hljs-keyword">private</span> SurfaceHolder holder; <span class="hljs-keyword">private</span> Camera mCamera; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mScreenWidth; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mScreenHeight; <span class="hljs-keyword">public</span> <span class="hljs-title">CameraSurfaceView</span>(Context context) { <span class="hljs-keyword">this</span>(context, <span class="hljs-keyword">null</span>); } <span class="hljs-keyword">public</span> <span class="hljs-title">CameraSurfaceView</span>(Context context, AttributeSet attrs) { <span class="hljs-keyword">this</span>(context, attrs, <span class="hljs-number">0</span>); } <span class="hljs-keyword">public</span> <span class="hljs-title">CameraSurfaceView</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) { <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr); mContext = context; getScreenMetrix(context); initView(); } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getScreenMetrix</span>(Context context) { WindowManager WM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = <span class="hljs-keyword">new</span> DisplayMetrics(); WM.getDefaultDisplay().getMetrics(outMetrics); mScreenWidth = outMetrics.widthPixels; mScreenHeight = outMetrics.heightPixels; } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initView</span>() { holder = getHolder();<span class="hljs-comment">//获得surfaceHolder引用</span> holder.addCallback(<span class="hljs-keyword">this</span>); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);<span class="hljs-comment">//设置类型</span> } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">surfaceCreated</span>(SurfaceHolder holder) { Log.i(TAG, <span class="hljs-string">"surfaceCreated"</span>); <span class="hljs-keyword">if</span> (mCamera == <span class="hljs-keyword">null</span>) { mCamera = Camera.open();<span class="hljs-comment">//开启相机</span> <span class="hljs-keyword">try</span> { mCamera.setPreviewDisplay(holder);<span class="hljs-comment">//摄像头画面显示在Surface上</span> } <span class="hljs-keyword">catch</span> (IOException e) { e.printStackTrace(); } } } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">surfaceChanged</span>(SurfaceHolder holder, <span class="hljs-keyword">int</span> format, <span class="hljs-keyword">int</span> width, <span class="hljs-keyword">int</span> height) { Log.i(TAG, <span class="hljs-string">"surfaceChanged"</span>); mCamera.startPreview(); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">surfaceDestroyed</span>(SurfaceHolder holder) { Log.i(TAG, <span class="hljs-string">"surfaceDestroyed"</span>); mCamera.stopPreview();<span class="hljs-comment">//停止预览</span> mCamera.release();<span class="hljs-comment">//释放相机资源</span> mCamera = <span class="hljs-keyword">null</span>; holder = <span class="hljs-keyword">null</span>; } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onAutoFocus</span>(<span class="hljs-keyword">boolean</span> success, Camera Camera) { <span class="hljs-keyword">if</span> (success) { Log.i(TAG, <span class="hljs-string">"onAutoFocus success="</span>+success); } }}</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li></ul>
添加相机和自动聚焦限权
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">uses-permission</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.permission.CAMERA"</span> /></span><span class="hljs-tag"><<span class="hljs-title">uses-feature</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.hardware.camera.autofocus"</span> /></span></code><ul class="pre-numbering"><li>1</li><li>2</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets_01.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li></ul>
将CameraSurfaceView
放在布局文件中,这里建议最外层为FrameLayout
,后面会用到。如此,我们便有了一个没有照相功能的相机。初次之外,仔细观察相机显示画面,图片是不是变形严重?那是因为我们还没有为相机设置各种参数。在预览前要设置摄像头的分辨率、预览分辨率和图片分辨率的宽高比保持一致。这样图片才不会变形。这是个比较难以理解的部分,想深刻理解还需读者自己动手去实践。
<code class="hljs avrasm has-numbering"> private void setCameraParams(Camera camera, int width, int height) { Log<span class="hljs-preprocessor">.i</span>(TAG,<span class="hljs-string">"setCameraParams width="</span>+width+<span class="hljs-string">" height="</span>+height)<span class="hljs-comment">;</span> Camera<span class="hljs-preprocessor">.Parameters</span> parameters = mCamera<span class="hljs-preprocessor">.getParameters</span>()<span class="hljs-comment">;</span> // 获取摄像头支持的PictureSize列表 List<Camera<span class="hljs-preprocessor">.Size</span>> pictureSizeList = parameters<span class="hljs-preprocessor">.getSupportedPictureSizes</span>()<span class="hljs-comment">;</span> for (Camera<span class="hljs-preprocessor">.Size</span> size : pictureSizeList) { Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"pictureSizeList size.width="</span> + size<span class="hljs-preprocessor">.width</span> + <span class="hljs-string">" size.height="</span> + size<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> } <span class="hljs-comment">/**从列表中选取合适的分辨率*/</span> Camera<span class="hljs-preprocessor">.Size</span> picSize = getProperSize(pictureSizeList, ((float) height / width))<span class="hljs-comment">;</span> if (null == picSize) { Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"null == picSize"</span>)<span class="hljs-comment">;</span> picSize = parameters<span class="hljs-preprocessor">.getPictureSize</span>()<span class="hljs-comment">;</span> } Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"picSize.width="</span> + picSize<span class="hljs-preprocessor">.width</span> + <span class="hljs-string">" picSize.height="</span> + picSize<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> // 根据选出的PictureSize重新设置SurfaceView大小 float w = picSize<span class="hljs-preprocessor">.width</span><span class="hljs-comment">;</span> float h = picSize<span class="hljs-preprocessor">.height</span><span class="hljs-comment">;</span> parameters<span class="hljs-preprocessor">.setPictureSize</span>(picSize<span class="hljs-preprocessor">.width</span>,picSize<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> this<span class="hljs-preprocessor">.setLayoutParams</span>(new FrameLayout<span class="hljs-preprocessor">.LayoutParams</span>((int) (height*(h/w)), height))<span class="hljs-comment">;</span> // 获取摄像头支持的PreviewSize列表 List<Camera<span class="hljs-preprocessor">.Size</span>> previewSizeList = parameters<span class="hljs-preprocessor">.getSupportedPreviewSizes</span>()<span class="hljs-comment">;</span> for (Camera<span class="hljs-preprocessor">.Size</span> size : previewSizeList) { Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"previewSizeList size.width="</span> + size<span class="hljs-preprocessor">.width</span> + <span class="hljs-string">" size.height="</span> + size<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> } Camera<span class="hljs-preprocessor">.Size</span> preSize = getProperSize(previewSizeList, ((float) height) / width)<span class="hljs-comment">;</span> if (null != preSize) { Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"preSize.width="</span> + preSize<span class="hljs-preprocessor">.width</span> + <span class="hljs-string">" preSize.height="</span> + preSize<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> parameters<span class="hljs-preprocessor">.setPreviewSize</span>(preSize<span class="hljs-preprocessor">.width</span>, preSize<span class="hljs-preprocessor">.height</span>)<span class="hljs-comment">;</span> } parameters<span class="hljs-preprocessor">.setJpegQuality</span>(<span class="hljs-number">100</span>)<span class="hljs-comment">; // 设置照片质量</span> if (parameters<span class="hljs-preprocessor">.getSupportedFocusModes</span>()<span class="hljs-preprocessor">.contains</span>(android<span class="hljs-preprocessor">.hardware</span><span class="hljs-preprocessor">.Camera</span><span class="hljs-preprocessor">.Parameters</span><span class="hljs-preprocessor">.FOCUS</span>_MODE_CONTINUOUS_PICTURE)) { parameters<span class="hljs-preprocessor">.setFocusMode</span>(android<span class="hljs-preprocessor">.hardware</span><span class="hljs-preprocessor">.Camera</span><span class="hljs-preprocessor">.Parameters</span><span class="hljs-preprocessor">.FOCUS</span>_MODE_CONTINUOUS_PICTURE)<span class="hljs-comment">;// 连续对焦模式</span> } mCamera<span class="hljs-preprocessor">.cancelAutoFocus</span>()<span class="hljs-comment">;//自动对焦。</span> // 设置PreviewDisplay的方向,效果就是将捕获的画面旋转多少度显示 // TODO 这里直接设置<span class="hljs-number">90</span>°不严谨,具体见https://developer<span class="hljs-preprocessor">.android</span><span class="hljs-preprocessor">.com</span>/reference/android/hardware/Camera<span class="hljs-preprocessor">.html</span><span class="hljs-preprocessor">#setPreviewDisplay%28android.view.SurfaceHolder%29</span> mCamera<span class="hljs-preprocessor">.setDisplayOrientation</span>(<span class="hljs-number">90</span>)<span class="hljs-comment">;</span> mCamera<span class="hljs-preprocessor">.setParameters</span>(parameters)<span class="hljs-comment">;</span> } <span class="hljs-comment">/** * 从列表中选取合适的分辨率 * 默认w:h = 4:3 * <p>tip:这里的w对应屏幕的height * h对应屏幕的width<p/> */</span> private Camera<span class="hljs-preprocessor">.Size</span> getProperSize(List<Camera<span class="hljs-preprocessor">.Size</span>> pictureSizeList, float screenRatio) { Log<span class="hljs-preprocessor">.i</span>(TAG, <span class="hljs-string">"screenRatio="</span> + screenRatio)<span class="hljs-comment">;</span> Camera<span class="hljs-preprocessor">.Size</span> result = null<span class="hljs-comment">;</span> for (Camera<span class="hljs-preprocessor">.Size</span> size : pictureSizeList) { float currentRatio = ((float) size<span class="hljs-preprocessor">.width</span>) / size<span class="hljs-preprocessor">.height</span><span class="hljs-comment">;</span> if (currentRatio - screenRatio == <span class="hljs-number">0</span>) { result = size<span class="hljs-comment">;</span> <span class="hljs-keyword">break</span><span class="hljs-comment">;</span> } } if (null == result) { for (Camera<span class="hljs-preprocessor">.Size</span> size : pictureSizeList) { float curRatio = ((float) size<span class="hljs-preprocessor">.width</span>) / size<span class="hljs-preprocessor">.height</span><span class="hljs-comment">;</span> if (curRatio == <span class="hljs-number">4</span>f / <span class="hljs-number">3</span>) {// 默认w:h = <span class="hljs-number">4</span>:<span class="hljs-number">3</span> result = size<span class="hljs-comment">;</span> <span class="hljs-keyword">break</span><span class="hljs-comment">;</span> } } } return result<span class="hljs-comment">;</span> }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li></ul>
进去的是屏幕宽高,出来的是调整好了的参数。在surfaceChanged
方法中执行mCamera.startPreview();
前调用setCameraParams(mCamera, mScreenWidth, mScreenHeight);
就可以了。最后要在AndroidManifest.xml
里设置activity
的方向Android:screenOrientation="portrait"
代码里有很多注释,其中也有我自己调试时候的Log,大家可以自己调试下,看看不同参数的效果。昨天调参数搞到一点多,都在折腾这个函数。唉,一把辛酸泪。
身为一个相机,居然不能照相?真是太丢脸了!下面给我们的相机添加上照相的功能。照相核心代码就一句:mCamera.takePicture(null, null, jpeg);
可以看到takePicture
方法有三个参数,分别是ShutterCallback
、PictureCallback
和PictureCallback
。这里我们只用了PictureCallback
<code class="hljs java has-numbering"> <span class="hljs-comment">// 拍照瞬间调用</span> <span class="hljs-keyword">private</span> Camera.ShutterCallback shutter = <span class="hljs-keyword">new</span> Camera.ShutterCallback() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onShutter</span>() { Log.i(TAG,<span class="hljs-string">"shutter"</span>); } }; <span class="hljs-comment">// 获得没有压缩过的图片数据</span> <span class="hljs-keyword">private</span> Camera.PictureCallback raw = <span class="hljs-keyword">new</span> Camera.PictureCallback() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onPictureTaken</span>(<span class="hljs-keyword">byte</span>[] data, Camera Camera) { Log.i(TAG, <span class="hljs-string">"raw"</span>); } }; <span class="hljs-comment">//创建jpeg图片回调数据对象</span> <span class="hljs-keyword">private</span> Camera.PictureCallback jpeg = <span class="hljs-keyword">new</span> Camera.PictureCallback() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onPictureTaken</span>(<span class="hljs-keyword">byte</span>[] data, Camera Camera) { BufferedOutputStream bos = <span class="hljs-keyword">null</span>; Bitmap bm = <span class="hljs-keyword">null</span>; <span class="hljs-keyword">try</span> { <span class="hljs-comment">// 获得图片</span> bm = BitmapFactory.decodeByteArray(data, <span class="hljs-number">0</span>, data.length); <span class="hljs-keyword">if</span> (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Log.i(TAG, <span class="hljs-string">"Environment.getExternalStorageDirectory()="</span>+Environment.getExternalStorageDirectory()); String filePath = <span class="hljs-string">"/sdcard/dyk"</span>+System.currentTimeMillis()+<span class="hljs-string">".jpg"</span>;<span class="hljs-comment">//照片保存路径</span> File file = <span class="hljs-keyword">new</span> File(filePath); <span class="hljs-keyword">if</span> (!file.exists()){ file.createNewFile(); } bos = <span class="hljs-keyword">new</span> BufferedOutputStream(<span class="hljs-keyword">new</span> FileOutputStream(file)); bm.compress(Bitmap.CompressFormat.JPEG, <span class="hljs-number">100</span>, bos);<span class="hljs-comment">//将图片压缩到流中</span> }<span class="hljs-keyword">else</span>{ Toast.makeText(mContext,<span class="hljs-string">"没有检测到内存卡"</span>, Toast.LENGTH_SHORT).show(); } } <span class="hljs-keyword">catch</span> (Exception e) { e.printStackTrace(); } <span class="hljs-keyword">finally</span> { <span class="hljs-keyword">try</span> { bos.flush();<span class="hljs-comment">//输出</span> bos.close();<span class="hljs-comment">//关闭</span> bm.recycle();<span class="hljs-comment">// 回收bitmap空间</span> mCamera.stopPreview();<span class="hljs-comment">// 关闭预览</span> mCamera.startPreview();<span class="hljs-comment">// 开启预览</span> } <span class="hljs-keyword">catch</span> (IOException e) { e.printStackTrace(); } } } };</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li></ul>
在jpeg#onPictureTaken()
里。我们将存储照片信息的byte[] data
解析成bitmap
,然后转换成JPG
格式的图片保存在SD卡中。注意finally
中最后两句mCamera.stopPreview();// 关闭预览 mCamera.startPreview();// 开启预览
上文也提到:当调用camera.takePiture()
方法后,camera
关闭了预览,这时需要调用startPreview()
来重新开启预览。如果不再次开启预览,则会一直停留在拍摄照片画面。为了方便外部调用拍照。这里我暴露了一个方法供外部拍照。
<code class="hljs cs has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">takePicture</span>(){ <span class="hljs-comment">//设置参数,并拍照</span> setCameraParams(mCamera, mScreenWidth, mScreenHeight); <span class="hljs-comment">// 当调用camera.takePiture方法后,camera关闭了预览,这时需要调用startPreview()来重新开启预览</span> mCamera.takePicture(<span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>, jpeg); }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>
在布局文件中添加一个Button
,点击Button
执行takePicture()
方法。不要忘了添加写SD卡限权
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">uses-permission</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.permission.WRITE_EXTERNAL_STORAGE"</span> /></span></code><ul class="pre-numbering"><li>1</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li></ul>
至此,一个具有照相并保存拍摄图片功能的相机就做出来了。But,我们就此满足了吗?要是为了这些简单的功能我也不会写这篇博客。这只是个开始
真正的开始
别人APP在照相的时候,屏幕上居然可以显示像效果图那样的框框啦、辅助点啦、图片bulabulabula~。在网上搜索一番实现方式,再加上一些自己的理解,构成了这篇博客。
上文布局文件一直没有贴,现在贴出来大家先扫一眼,有些控件会在接下来展示
<code class="hljs xml has-numbering"><span class="hljs-pi"><?xml version="1.0" encoding="utf-8"?></span><span class="hljs-tag"><<span class="hljs-title">FrameLayout</span> <span class="hljs-attribute">xmlns:android</span>=<span class="hljs-value">"http://schemas.android.com/apk/res/android"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span> <span class="hljs-tag"><<span class="hljs-title">com.dyk.cameratest.view.CameraSurfaceView</span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/cameraSurfaceView"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> /></span> <span class="hljs-tag"><<span class="hljs-title">com.dyk.cameratest.view.RectOnCamera</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span> /></span> <span class="hljs-tag"><<span class="hljs-title">RelativeLayout</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"match_parent"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"match_parent"</span>></span> <span class="hljs-tag"><<span class="hljs-title">Button</span> <span class="hljs-attribute">android:layout_alignParentBottom</span>=<span class="hljs-value">"true"</span> <span class="hljs-attribute">android:layout_centerHorizontal</span>=<span class="hljs-value">"true"</span> <span class="hljs-attribute">android:layout_marginBottom</span>=<span class="hljs-value">"20dp"</span> <span class="hljs-attribute">android:id</span>=<span class="hljs-value">"@+id/takePic"</span> <span class="hljs-attribute">android:layout_width</span>=<span class="hljs-value">"80dp"</span> <span class="hljs-attribute">android:layout_height</span>=<span class="hljs-value">"50dp"</span> <span class="hljs-attribute">android:background</span>=<span class="hljs-value">"#88427ac7"</span> <span class="hljs-attribute">android:text</span>=<span class="hljs-value">"拍照"</span> <span class="hljs-attribute">android:textColor</span>=<span class="hljs-value">"#aaa"</span> /></span> <span class="hljs-tag"></<span class="hljs-title">RelativeLayout</span>></span><span class="hljs-tag"></<span class="hljs-title">FrameLayout</span>></span></code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li></ul>
布局文件的最外层是个FrameLayout
,我们知道FrameLayout
是自带覆盖效果的。由来这个思路接下来就很简单了。编程重要的是思想,思想有了,其余的就剩具体的实现细节。
自定义边边框框
为了和CameraSurfaceView
区分开,再自定义一个RectOnCamera
专门用来画边边框框这些东西。这样做还一个好处是方便维护,不至于将所有东西都放在一个View中。
RectOnCamera
<code class="hljs java has-numbering"><span class="hljs-keyword">package</span> com.dyk.cameratest.view;...<span class="hljs-javadoc">/** * Created by 一口仨馍 on 2016/4/7. */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RectOnCamera</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">View</span> {</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"CameraSurfaceView"</span>; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mScreenWidth; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> mScreenHeight; <span class="hljs-keyword">private</span> Paint mPaint; <span class="hljs-keyword">private</span> RectF mRectF; <span class="hljs-comment">// 圆</span> <span class="hljs-keyword">private</span> Point centerPoint; <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> radio; <span class="hljs-keyword">public</span> <span class="hljs-title">RectOnCamera</span>(Context context) { <span class="hljs-keyword">this</span>(context, <span class="hljs-keyword">null</span>); } <span class="hljs-keyword">public</span> <span class="hljs-title">RectOnCamera</span>(Context context, AttributeSet attrs) { <span class="hljs-keyword">this</span>(context, attrs, <span class="hljs-number">0</span>); } <span class="hljs-keyword">public</span> <span class="hljs-title">RectOnCamera</span>(Context context, AttributeSet attrs, <span class="hljs-keyword">int</span> defStyleAttr) { <span class="hljs-keyword">super</span>(context, attrs, defStyleAttr); getScreenMetrix(context); initView(context); } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">getScreenMetrix</span>(Context context) { WindowManager WM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = <span class="hljs-keyword">new</span> DisplayMetrics(); WM.getDefaultDisplay().getMetrics(outMetrics); mScreenWidth = outMetrics.widthPixels; mScreenHeight = outMetrics.heightPixels; } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initView</span>(Context context) { mPaint = <span class="hljs-keyword">new</span> Paint(); mPaint.setAntiAlias(<span class="hljs-keyword">true</span>);<span class="hljs-comment">// 抗锯齿</span> mPaint.setDither(<span class="hljs-keyword">true</span>);<span class="hljs-comment">// 防抖动</span> mPaint.setColor(Color.RED); mPaint.setStrokeWidth(<span class="hljs-number">5</span>); mPaint.setStyle(Paint.Style.STROKE);<span class="hljs-comment">// 空心</span> <span class="hljs-keyword">int</span> marginLeft = (<span class="hljs-keyword">int</span>) (mScreenWidth*<span class="hljs-number">0.15</span>); <span class="hljs-keyword">int</span> marginTop = (<span class="hljs-keyword">int</span>) (mScreenHeight * <span class="hljs-number">0.25</span>); mRectF = <span class="hljs-keyword">new</span> RectF(marginLeft, marginTop, mScreenWidth - marginLeft, mScreenHeight - marginTop); centerPoint = <span class="hljs-keyword">new</span> Point(mScreenWidth/<span class="hljs-number">2</span>, mScreenHeight/<span class="hljs-number">2</span>); radio = (<span class="hljs-keyword">int</span>) (mScreenWidth*<span class="hljs-number">0.1</span>); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDraw</span>(Canvas canvas) { <span class="hljs-keyword">super</span>.onDraw(canvas); mPaint.setColor(Color.RED); canvas.drawRect(mRectF, mPaint); mPaint.setColor(Color.WHITE); Log.i(TAG, <span class="hljs-string">"onDraw"</span>); canvas.drawCircle(centerPoint.x,centerPoint.y, radio,mPaint);<span class="hljs-comment">// 外圆</span> canvas.drawCircle(centerPoint.x,centerPoint.y, radio - <span class="hljs-number">20</span>,mPaint); <span class="hljs-comment">// 内圆</span> }}</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li></ul>
这里简单的画了一个类似二维码扫描的框框,还有一个类似聚焦的内外圆。那么问题来了,聚焦的内外圆要随着手指滑而改变位置,而且要有聚焦的效果。可又和具有聚焦功能的CameraSurfaceView
不是同一个类,不仅如此聚焦内外圆还完全覆盖了CameraSurfaceView
。要处理这种问题,需要接口回调。这就是思想下面的细节。现在虽然确定接口回调,但还有一个问题,CameraSurfaceView
类和RectOnCamera
类中都没有对方的对象或者引用。没错,通过共同持有RectOnCamera
和CameraSurfaceView
的Activity
可以实现此功能。下面是具体的实现方法
动起来
首先,想要随着手指的滑动而改变RectOnCamera的位置肯定是要复写onTouchEvent()方法
<code class="hljs cs has-numbering"> @Override <span class="hljs-keyword">public</span> boolean <span class="hljs-title">onTouchEvent</span>(MotionEvent <span class="hljs-keyword">event</span>) { <span class="hljs-keyword">switch</span> (<span class="hljs-keyword">event</span>.getAction()){ <span class="hljs-keyword">case</span> MotionEvent.ACTION_DOWN: <span class="hljs-keyword">case</span> MotionEvent.ACTION_MOVE: <span class="hljs-keyword">case</span> MotionEvent.ACTION_UP: <span class="hljs-keyword">int</span> x = (<span class="hljs-keyword">int</span>) <span class="hljs-keyword">event</span>.getX(); <span class="hljs-keyword">int</span> y = (<span class="hljs-keyword">int</span>) <span class="hljs-keyword">event</span>.getY(); centerPoint = <span class="hljs-keyword">new</span> Point(x, y); invalidate(); <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>; } <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>; }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>
其次,定义回调接口
<code class="hljs java has-numbering"> <span class="hljs-keyword">private</span> IAutoFocus mIAutoFocus; <span class="hljs-javadoc">/** 聚焦的回调接口 */</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IAutoFocus</span>{</span> <span class="hljs-keyword">void</span> autoFocus(); } <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setIAutoFocus</span>(IAutoFocus mIAutoFocus) { <span class="hljs-keyword">this</span>.mIAutoFocus = mIAutoFocus; }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>
在onTouchEvent()
中return
前加入
<code class="hljs cs has-numbering"> <span class="hljs-keyword">if</span> (mIAutoFocus != <span class="hljs-keyword">null</span>){ mIAutoFocus.autoFocus(); }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>
至此我们的回调接口已经定义好了,此时还需要CameraSurfaceView
暴露一个聚焦方法,以便Activity
调用
<code class="hljs cs has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAutoFocus</span>(){ mCamera.autoFocus(<span class="hljs-keyword">this</span>); }</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><div class="save_code tracking-ad" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>
准备工作已经全部完成,下面请看Activity的具体实现:
<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Activity</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">View</span>.<span class="hljs-title">OnClickListener</span>,<span class="hljs-title">RectOnCamera</span>.<span class="hljs-title">IAutoFocus</span>{</span> <span class="hljs-keyword">private</span> CameraSurfaceView mCameraSurfaceView; <span class="hljs-keyword">private</span> RectOnCamera mRectOnCamera; <span class="hljs-keyword">private</span> Button takePicBtn; <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isClicked; <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) { <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); <span class="hljs-comment">// 全屏显示 </span> getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); mCameraSurfaceView = (CameraSurfaceView) findViewById(R.id.cameraSurfaceView); mRectOnCamera = (RectOnCamera) findViewById(R.id.rectOnCamera); takePicBtn= (Button) findViewById(R.id.takePic); mRectOnCamera.setIAutoFocus(<span class="hljs-keyword">this</span>); takePicBtn.setOnClickListener(<span class="hljs-keyword">this</span>); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(View v) { <span class="hljs-keyword">switch</span> (v.getId()){ <span class="hljs-keyword">case</span> R.id.takePic: mCameraSurfaceView.takePicture(); <span class="hljs-keyword">break</span>; <span class="hljs-keyword">default</span>: <span class="hljs-keyword">break</span>; } } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">autoFocus</span>() { mCameraSurfaceView.setAutoFocus(); }}</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li></ul>
可以看到,MainActivity
实现了IAutoFocus
接口,并且在复写的IAutoFocus#autoFocus()
方法中,调用了CameraSurfaceView
暴露出来的方法setAutoFocus()
。至此,在RectOnCamera
每次的滑动过程中都会改变聚焦内外圆的位置,还会增加聚焦功能。一心二用甚至一心多用岂不是更好。
结束语
在经历两次断电没保存和一次CSDN服务器错误内容丢失之后终究还是完成了这篇博客,实属不易。十分感谢能听我啰嗦到结尾~
PS:Demo界面并没有做的很精致,只是提供了一种思路。按照此思路能做出比较华丽的效果,授人以鱼不如授人以渔。
2016.10.12 在经历了上述种种磨难之后,终于发表了这篇博文,然而发表没几天,被我自己覆盖了。这下博文是真的丢了。心塞ing。今天没事百度下自己CSDN昵称“一口仨馍”,发现其他网站爬过这篇博文,随后我复制了自己原创的博文,再次发表。感谢那些爬我博文还不署名的网站。谢谢你全家。
源码下载
http://download.csdn.net/detail/qq_17250009/9484160
- Android 手把手带你玩转自定义相机
- Android 手把手带你玩转自定义相机
- [转载]Android 手把手带你玩转自定义相机
- Android 手把手带你玩转自定义相机
- Android 手把手带你玩转自定义相机
- Android 手把手带你玩转自定义相机
- Android 手把手带你玩转自定义相机
- 手把手带你画一个 时尚仪表盘 Android 自定义View
- 手把手带你画一个 时尚仪表盘 Android 自定义View
- 手把手带你画一个 时尚仪表盘 Android 自定义View
- 手把手带你画一个 时尚仪表盘 Android 自定义View
- 手把手教你玩转android应用Microsoft Remote Desktop
- 自定义view详解,手把手带你画一个漂亮蜂窝view Android自定义view
- 手把手教你玩转ARP包
- 手把手教你玩转ARP包
- 手把手教你玩转ARP包
- 手把手教你玩转ARP包
- 手把手教你玩转ARP包
- NYOJ - 488 - 素数环(回溯法)
- LeetCode 412. Fizz Buzz
- codeforces 727A 规律
- 记一个 sharepreferences
- Linux命令之"whereis"
- Android 手把手带你玩转自定义相机
- 每天一个常用的linux命令(11)--which
- 中国剩余定理(转)
- TOP 10 开源的推荐系统简介
- JDBC 练习
- java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
- 求两字符串的最长公共连续子串
- OD选项设置-本地变量的显示格式
- 算法之——快速排序