android控件库(2)-仿Google Camera 的对焦效果
一直很喜欢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>
代码很简单,注释已经写得很详细了,相信大家都能看得懂。
最终效果:
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库