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

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

package com.example.test.view;

import com.example.test.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View; /**
* Focus View
* @author xp.chen
*/
public class FocusView extends View { public FocusView(Context context) {
super(context);
} public FocusView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
} private Paint mPaint; private void init(Context context, AttributeSet attrs) {
// init paint
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FocusView);
int count = typedArray.getIndexCount();
for (int i = 0; i < count; i++) {
int id = typedArray.getIndex(i);
switch (id) {
case R.styleable.FocusView_focusColor:
paintColor = typedArray.getColor(id, Color.WHITE);
break;
case R.styleable.FocusView_focusDefaultRadius:
radius = typedArray.getFloat(id, 20);
break;
case R.styleable.FocusView_focusMaxRadius:
maxRadius = typedArray.getFloat(id, 100);
break;
default:
break;
}
} typedArray.recycle(); mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(3);
mPaint.setColor(paintColor); } // addGestureRecognizer UITapGestureRecognizer
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: // UIGestureRecognizerStateBegan
if (!isStart) {
centerX = event.getX();
centerY = event.getY();
// 重量选框参数
isStart = true;
isNeedDismiss = false;
paintAlpha = 255;
mPaint.setAlpha(paintAlpha);
radius = 20;
invalidate();
mHandler.obtainMessage(0).sendToTarget();
}
break;
case MotionEvent.ACTION_MOVE: // UIGestureRecognizerStateChange
break;
case MotionEvent.ACTION_UP: // UIGestureRecognizerStateEnd
break;
default:
break;
}
return super.onTouchEvent(event);
} private Handler mHandler = new Handler() { @Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0: // update size
radius += 5;
if (radius >= maxRadius) { // 若将要绘制的尺寸大于约束的最大尺寸,则将该尺寸还原
radius -= 5;
mHandler.sendEmptyMessageDelayed(1, 1000); // 使选框停留1s后逐渐消失
} else {
mHandler.sendEmptyMessageDelayed(0, (long)(200f/radius));
invalidate(); // setNeedDisplay
}
break;
case 1: // update alpha
paintAlpha -= 20; // 当选框达到最大后,就不断改变其透明度,直至透明度为0,本次绘制过程结束
if (paintAlpha <=0) {
isNeedDismiss = true;
invalidate();
isStart = false;
} else {
mPaint.setAlpha(paintAlpha);
invalidate();
mHandler.sendEmptyMessageDelayed(1,15);
}
break;
default:
break;
}
}
}; @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// CGSize
// setMeasuredDimension(measuredWidth, measuredHeight);
} private float centerX; // 焦点中心点X
private float centerY; // 焦点中心点Y
private float radius = 20; // 焦点选框的最小半径
private float maxRadius = 100; // 焦点选框的最大半径
private int paintAlpha = 255; // 焦点选框的最大透明度
private int paintColor = Color.WHITE; /**
* 设置焦点选框的初始半径
* @param radius
*/
public void setFocusCircleRadius(float radius) {
this.radius = radius;
} /**
* 设置焦点选框的最大半径
* @param radius
*/
public void setFocusCircleMaxRadius(float radius) {
this.maxRadius = radius;
} /**
* 设置焦点选框的颜色
* @param color
*/
public void setFocusCircleColor(int color) {
this.paintColor = color;
mPaint.setColor(color);
} /**
* 焦点选框是否需要消失
*/
private boolean isNeedDismiss = true; /**
* 是否已经开始绘制的标志位。如果已经开始绘制,则拒绝下一次点击绘制请求
*/
private boolean isStart = false; // drawRect
@Override
protected void onDraw(Canvas canvas) { if (!isNeedDismiss) { // 若绘制过程结束,则清除焦点框
canvas.drawCircle(centerX, centerY, radius, mPaint);
} } }

attrs.xml

    <declare-styleable name="FocusView">
<attr name="focusDefaultRadius" format="float"/>
<attr name="focusMaxRadius" format="float"/>
<attr name="focusColor" format="color"/>
</declare-styleable>

activity.main.xml

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.test"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
> <com.example.test.view.FocusView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:focusColor = "#fff"
app:focusMaxRadius = "100"
/> </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. 算法与数据结构之顺序查找(C语言)

    #include<stdio.h> #include<stdlib.h> //顺序查找基本思想:从线性表的一端开始,逐个检查关键字是否满足给定的条件 int Sequentia ...

  2. while 循环 于 for循环语句

    while 循环 while 循环 while 条件: 如果条件是真的,就继续的循环 如果条件是假的,就停止循环 循环的意思就是让程序重复地执行某些语句,whiler循环就是循环结构的一种,当事先不知 ...

  3. js checkbox获取选中的值

    //将选择标签 var addCode = function () { var codes = []; var elements = document.getElementsByName(" ...

  4. 绘制图形与3D增强技巧(三)----三角形图元TRANGLE

    1. glBegin(GL_TRANGLES); ........ glend(); 2.多边形的环绕方向:逆时针和顺时针的正反面 GLFront(GL_CCW)和GLFront(GL_CW); 3. ...

  5. 如何使用maven建一个web3.0的项目

    使用eclipse手动建一个maven的web project可能会有版本不合适的情况,例如使用spring的websocket需要web3.0什么的,不全面的修改可能会出现各种红叉,甚是苦恼.我从我 ...

  6. Leetcode 280. Wiggle Sort

    Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] < ...

  7. 关于PHP代码审计和漏洞挖掘的一点思考

    这里对PHP的代码审计和漏洞挖掘的思路做一下总结,都是个人观点,有不对的地方请多多指出. PHP的漏洞有很大一部分是来自于程序员本身的经验不足,当然和服务器的配置有关,但那属于系统安全范畴了,我不太懂 ...

  8. Android中运行的错误:java.lang.UnsatisfiedLinkError: Couldn't load locSDK3: findLibrary returned null.

    ---恢复内容开始--- 明明已经加入了liblocSDK3.so,但总是无法定位.提示错误java.lang.UnsatisfiedLinkError: Couldn't load locSDK3: ...

  9. 解析:使用easyui的form提交表单,在IE下出现类似附件下载时提示是否保存的现象

    之前开发时遇到的一个问题,使用easyui的form提交表单,在Chrome下时没问题的,但是在IE下出现类似附件下载时提示是否保存的现象. 这里记录一下如何解决的.其实这个现象不光是easyui的f ...

  10. CentOS同步时间

    用date查看系统当前时间,date -R 可查看时区. CentOS 同步时间由ntp服务提供,可以用"yum install ntp -y"安装. 装完后运行命令 ntpdat ...