一直很喜欢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. 学习WebSocket(一):Spring WebSocket的简单使用

    1.什么是websocket? WebSocket协议定义了一种web应用的新功能,它实现了服务器端和客户端的全双工通信.全双工通信即通信的双方可以同时发送和接收信息 的信息交互方式.它是继Java ...

  2. bzoj 3518 Dirichlet卷积

    详情见代码,回头再填坑... #include<iostream> #include<cstdio> #include<algorithm> #include< ...

  3. js-JavaScript高级程序设计学习笔记15

    第十七章 错误处理与调试 1.try-catch语句.如果try块中的任何代码发生了错误,就会立即退出执行开始执行catch块.必须要给catch的错误对象起名字.不同浏览器都有一个message属性 ...

  4. 树莓派实现远程开机局域网电脑(WOL协议+etherwake+华硕主板Z97)秒变花生壳开机棒

    一.花生壳映射树莓派 参考: http://www.cnblogs.com/EasonJim/p/6100181.html http://www.cnblogs.com/EasonJim/p/6100 ...

  5. Android成长日记-数据存储之SQLite[1]

    [SQLite简介] SQLite是R.Richard Hipp用C语言编写的开源嵌入式数据库引擎.它支持大多数的SQL92标准,并且可以在所有主要的操作系统上运行 ---支持高达2TB大小的数据库: ...

  6. 谈谈favicon和他带来的问题

    favicon.ico介绍 favicon.ico是个什么东西呢,也许见得太多都习以为常了(我就是这样,直到写这篇文章之前才知道),看看维基百科的解释: Favicon是favorites icon的 ...

  7. SLF4J的好处

    原来我们使用log4j去打印日志,如果我们要更改日志记录器,比如用comms-Logging,那我们在代码里面还要改每个类的引用包,但是如果用slf4j的话只要在配置的时候改下,代码完全用slf4j的 ...

  8. RabbitMQctl命令

    RabbitMQControl RabbitMQ提供了可视化的网页供我们进行一些配置与操作,但是ctl的命令比UI来的专业的多,一些UI无法完成的操作就需要使用ctl命令来进行处理了 这里是官方的文档 ...

  9. (原)String、StringBuilder、StringBuffer作为形参

    今天在刷一道算法题时,突然遇到StringBuilder作为形参和String作为形参时,最终得出来的结果不同.故尝试了几个demo看看它们之间的区别. 当String类型作为参数时, public ...

  10. HDU 1002 A + B Problem II

    A + B Problem II   Time Limit: 1000MS      Memory Limit: 65536K Total Submissions: 16104    Accepted ...