一直很喜欢Google Camera的自动对焦效果,今日闲来无事,自己做了个:

废话不多说,代码才是王道:

  1. package com.example.test.view;
  2.  
  3. import com.example.test.R;
  4.  
  5. import android.content.Context;
  6. import android.content.res.TypedArray;
  7. import android.graphics.Canvas;
  8. import android.graphics.Color;
  9. import android.graphics.Paint;
  10. import android.os.Handler;
  11. import android.os.Message;
  12. import android.util.AttributeSet;
  13. import android.view.MotionEvent;
  14. import android.view.View;
  15.  
  16. /**
  17. * Focus View
  18. * @author xp.chen
  19. */
  20. public class FocusView extends View {
  21.  
  22. public FocusView(Context context) {
  23. super(context);
  24. }
  25.  
  26. public FocusView(Context context, AttributeSet attrs) {
  27. super(context, attrs);
  28. init(context,attrs);
  29. }
  30.  
  31. private Paint mPaint;
  32.  
  33. private void init(Context context, AttributeSet attrs) {
  34. // init paint
  35. TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FocusView);
  36. int count = typedArray.getIndexCount();
  37. for (int i = 0; i < count; i++) {
  38. int id = typedArray.getIndex(i);
  39. switch (id) {
  40. case R.styleable.FocusView_focusColor:
  41. paintColor = typedArray.getColor(id, Color.WHITE);
  42. break;
  43. case R.styleable.FocusView_focusDefaultRadius:
  44. radius = typedArray.getFloat(id, 20);
  45. break;
  46. case R.styleable.FocusView_focusMaxRadius:
  47. maxRadius = typedArray.getFloat(id, 100);
  48. break;
  49. default:
  50. break;
  51. }
  52. }
  53.  
  54. typedArray.recycle();
  55.  
  56. mPaint = new Paint();
  57. mPaint.setAntiAlias(true);
  58. mPaint.setStyle(Paint.Style.STROKE);
  59. mPaint.setStrokeWidth(3);
  60. mPaint.setColor(paintColor);
  61.  
  62. }
  63.  
  64. // addGestureRecognizer UITapGestureRecognizer
  65. @Override
  66. public boolean onTouchEvent(MotionEvent event) {
  67. switch (event.getAction()) {
  68. case MotionEvent.ACTION_DOWN: // UIGestureRecognizerStateBegan
  69. if (!isStart) {
  70. centerX = event.getX();
  71. centerY = event.getY();
  72. // 重量选框参数
  73. isStart = true;
  74. isNeedDismiss = false;
  75. paintAlpha = 255;
  76. mPaint.setAlpha(paintAlpha);
  77. radius = 20;
  78. invalidate();
  79. mHandler.obtainMessage(0).sendToTarget();
  80. }
  81. break;
  82. case MotionEvent.ACTION_MOVE: // UIGestureRecognizerStateChange
  83. break;
  84. case MotionEvent.ACTION_UP: // UIGestureRecognizerStateEnd
  85. break;
  86. default:
  87. break;
  88. }
  89. return super.onTouchEvent(event);
  90. }
  91.  
  92. private Handler mHandler = new Handler() {
  93.  
  94. @Override
  95. public void handleMessage(Message msg) {
  96. super.handleMessage(msg);
  97. switch (msg.what) {
  98. case 0: // update size
  99. radius += 5;
  100. if (radius >= maxRadius) { // 若将要绘制的尺寸大于约束的最大尺寸,则将该尺寸还原
  101. radius -= 5;
  102. mHandler.sendEmptyMessageDelayed(1, 1000); // 使选框停留1s后逐渐消失
  103. } else {
  104. mHandler.sendEmptyMessageDelayed(0, (long)(200f/radius));
  105. invalidate(); // setNeedDisplay
  106. }
  107. break;
  108. case 1: // update alpha
  109. paintAlpha -= 20; // 当选框达到最大后,就不断改变其透明度,直至透明度为0,本次绘制过程结束
  110. if (paintAlpha <=0) {
  111. isNeedDismiss = true;
  112. invalidate();
  113. isStart = false;
  114. } else {
  115. mPaint.setAlpha(paintAlpha);
  116. invalidate();
  117. mHandler.sendEmptyMessageDelayed(1,15);
  118. }
  119. break;
  120. default:
  121. break;
  122. }
  123. }
  124. };
  125.  
  126. @Override
  127. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  128. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  129. // CGSize
  130. // setMeasuredDimension(measuredWidth, measuredHeight);
  131. }
  132.  
  133. private float centerX; // 焦点中心点X
  134. private float centerY; // 焦点中心点Y
  135. private float radius = 20; // 焦点选框的最小半径
  136. private float maxRadius = 100; // 焦点选框的最大半径
  137. private int paintAlpha = 255; // 焦点选框的最大透明度
  138. private int paintColor = Color.WHITE;
  139.  
  140. /**
  141. * 设置焦点选框的初始半径
  142. * @param radius
  143. */
  144. public void setFocusCircleRadius(float radius) {
  145. this.radius = radius;
  146. }
  147.  
  148. /**
  149. * 设置焦点选框的最大半径
  150. * @param radius
  151. */
  152. public void setFocusCircleMaxRadius(float radius) {
  153. this.maxRadius = radius;
  154. }
  155.  
  156. /**
  157. * 设置焦点选框的颜色
  158. * @param color
  159. */
  160. public void setFocusCircleColor(int color) {
  161. this.paintColor = color;
  162. mPaint.setColor(color);
  163. }
  164.  
  165. /**
  166. * 焦点选框是否需要消失
  167. */
  168. private boolean isNeedDismiss = true;
  169.  
  170. /**
  171. * 是否已经开始绘制的标志位。如果已经开始绘制,则拒绝下一次点击绘制请求
  172. */
  173. private boolean isStart = false;
  174.  
  175. // drawRect
  176. @Override
  177. protected void onDraw(Canvas canvas) {
  178.  
  179. if (!isNeedDismiss) { // 若绘制过程结束,则清除焦点框
  180. canvas.drawCircle(centerX, centerY, radius, mPaint);
  181. }
  182.  
  183. }
  184.  
  185. }

attrs.xml

  1. <declare-styleable name="FocusView">
  2. <attr name="focusDefaultRadius" format="float"/>
  3. <attr name="focusMaxRadius" format="float"/>
  4. <attr name="focusColor" format="color"/>
  5. </declare-styleable>

activity.main.xml

  1. <RelativeLayout
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res/com.example.test"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:background="#000"
  8. >
  9.  
  10. <com.example.test.view.FocusView
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. app:focusColor = "#fff"
  14. app:focusMaxRadius = "100"
  15. />
  16.  
  17. </RelativeLayout>

代码很简单,注释已经写得很详细了,相信大家都能看得懂。

最终效果:

android控件库(2)-仿Google Camera 的对焦效果的更多相关文章

  1. Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现

    Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现 2015-03-10 22:38 28419人阅读 评论(17) 收藏 举报  分类: Android ...

  2. Android控件Gridview实现仿支付宝首页,Fragment底部按钮切换和登录圆形头像

    此案例主要讲的是Android控件Gridview(九宫格)完美实现仿支付宝首页,包含添加和删除功能:Fragment底部按钮切换的效果,包含四个模块,登录页面圆形头像等,一个小项目的初始布局. 效果 ...

  3. Android控件-ViewPager(仿微信引导界面)

    什么是ViewPager? ViewPager是安卓3.0之后提供的新特性,继承自ViewGroup,专门用以实现左右滑动切换View的效果. 如果想向下兼容就必须要android-support-v ...

  4. Android 控件进阶修炼-仿360手机卫士波浪球进度控件

    技术:Android+java   概述 像360卫士的波浪球进度的效果,一般最常用的方法就是 画线的方式,先绘sin线或贝塞尔曲线,然后从左到右绘制竖线,然后再裁剪圆区域. 今天我这用图片bitma ...

  5. android控件库(1)-带删除功能的EditText

    DJEditText.java /** * Created by xp.chen on 2016/11/25. */ public class DJEditText extends AppCompat ...

  6. UIAutomator定位Android控件的方法

    UIAutomator各种控件定位的方法. 1. 背景 使用SDK自带的NotePad应用,尝试去获得在NotesList那个Activity里的Menu Options上面的那个Add note菜单 ...

  7. android控件的属性

    android控件的属性 本节描述android空间的位置,内容等相关属性及属性的含义 第一类:属性值为true或false android:layout_centerHrizontal 水平居中 ( ...

  8. JavaFX的扩展控件库ControlsFX介绍

    声明:   本博客文章原创类别的均为个人原创,版权所有.转载请注明出处: http://blog.csdn.net/ml3947,另外本人的个人博客:http://www.wjfxgame.com. ...

  9. 【转】UIAutomator定位Android控件的方法实践和建议(Appium姊妹篇)

    原文地址:http://blog.csdn.net/zhubaitian/article/details/39777951 在本人之前的一篇文章<<Appium基于安卓的各种FindEle ...

随机推荐

  1. Android获取屏幕宽和高

    android获取屏幕的高度和宽度用到WindowManager这个类,两种方法:   1.WindowManager wm = (WindowManager) getContext()        ...

  2. NPOI简介

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. (一)传统操作Excel遇到的问题: 1.如果是.NET,需要在服务器端 ...

  3. linux永久更改eth0的ip地址后仍然ping不通过

    编辑文件/etc/sysconfig/network-scripts/ifcfg-eth0 引用:DEVICE=eth0 //设备名称,不要修改 BOOTPROTO=static //不要修改 BRO ...

  4. Hash_P1026毒药?解药?

    #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> ...

  5. SPOJ GSS3 Can you answer these queries III

    Time Limit: 330MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are g ...

  6. [NOIP2015] 提高组 洛谷P2668 斗地主

    题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...

  7. UDP打洞、P2P组网方式研究

    catalogue . NAT概念 . P2P概念 . UDP打洞 . P2P DEMO . ZeroNet P2P 1. NAT概念 在STUN协议中,根据内部终端的地址(LocalIP:Local ...

  8. 数据结构作业——order(二叉树遍历)

    order Description 给出一棵二叉树的中序遍历和每个节点的父节点,求这棵二叉树的先序和后 序遍历. Input 输入第一行为一个正整数 n 表示二叉树的节点数目, 节点编号从 1 到 n ...

  9. JavaWeb---总结(十七)JSP中的九个内置对象

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  10. BZOJ4415: [Shoi2013]发牌

    显然可以线段树或树状数组上二分. 然而直接写splay在bzoj上并不会T. 然而发这题的目的只是因为我又忘了return了啊啊啊啊(TдT) 内心十分崩溃.关键是在本地还能过. #include&l ...