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>
复制代码

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

最终效果:

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   夜行过客  阅读(1307)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示