package com.yydcdut.note.widget.camera; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.yydcdut.note.R; /** * Created by yuyidong on 15/8/27. */ public class FocusView extends View { /* * Action state */ private int mActionState; private static final int STATE_NOTHING = -1; private static final int STATE_2_FINGERS = -2; /* * Handler的一些东西 */ private Handler mHandler; public static final int IMAGE_DISAPPEAR = 0; public static final int IMAGE_DISAPPEAR_GOOD = 1; /** * 前置摄像头不支持聚焦,所以这个标志位来判断 */ private boolean mIsSupport = false; /** * 一旦Move之后,手指速度快了的话就跟不上move了,所以用这个标志位 */ private boolean mMoveFollow = false; /** * 最大宽度 */ private final float MAX_LENGTH = this.getContext().getResources().getDimension(R.dimen.focus_length_max); /** * 当前宽度 */ private float mLength = this.getContext().getResources().getDimension(R.dimen.focus_length_min); /* * 坐标 */ private float mX; private float mY; /* * 画笔 */ private Paint mPaint; private int mViewWidth; private int mViewHeight; public FocusView(Context context) { this(context, null); } public FocusView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FocusView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initLooper(); mPaint = new Paint(); mPaint.setColor(Color.YELLOW); mPaint.setStrokeWidth(2); mPaint.setStyle(Paint.Style.STROKE); mPaint.setAntiAlias(true); } private void initLooper() { mHandler = new Handler(Looper.getMainLooper(), mCallback); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mViewWidth > 0 && mViewHeight > 0) { setMeasuredDimension(mViewWidth, mViewHeight); } } @Override protected void onDraw(Canvas canvas) { if (!mIsSupport) { return; } super.onDraw(canvas); canvas.drawArc(calculateRectF(), 0, 360, false, mPaint); if (mActionState == MotionEvent.ACTION_UP && mLength <= MAX_LENGTH) { mLength += 5; if (mLength >= MAX_LENGTH) { mLength = MAX_LENGTH; } invalidate(); } else if (mActionState == MotionEvent.ACTION_MOVE) { mLength -= 2; if (mLength <= getResources().getDimension(R.dimen.focus_length_min)) { mLength = getResources().getDimension(R.dimen.focus_length_min); } } } /** * 计算位置 * * @return */ private RectF calculateRectF() { return new RectF(mX - mLength / 2, mY - mLength / 2, mX + mLength / 2, mY + mLength / 2); } /** * 聚焦成功 */ private void focusSuccess() { if (!mIsSupport) { return; } this.setVisibility(VISIBLE); mPaint.setColor(Color.YELLOW); invalidate(); mHandler.sendEmptyMessageDelayed(IMAGE_DISAPPEAR_GOOD, 400); } /** * 停止聚焦 */ private void stopFocus() { if (!mIsSupport) { return; } this.setVisibility(GONE); } private Handler.Callback mCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case IMAGE_DISAPPEAR: focusSuccess(); break; case IMAGE_DISAPPEAR_GOOD: stopFocus(); if (mOnFocusStateChangedListener != null) { mOnFocusStateChangedListener.onFocusDisappeared(); } break; } return false; } }; public void setNotSupport() { mIsSupport = false; } /** * 开始聚焦动画 * * @param x * @param y * @return */ public boolean startFocusing(float x, float y) { if (mHandler.hasMessages(IMAGE_DISAPPEAR) || mHandler.hasMessages(IMAGE_DISAPPEAR_GOOD)) { return false; } mPaint.setColor(Color.YELLOW); this.setVisibility(VISIBLE); mLength = getContext().getResources().getDimension(R.dimen.focus_length_min); mActionState = MotionEvent.ACTION_UP; mX = x; mY = y; invalidate(); mHandler.sendEmptyMessageDelayed(IMAGE_DISAPPEAR, 1000); if (mOnFocusStateChangedListener != null) { mOnFocusStateChangedListener.onBeginFocusing(x, y); } return true; } public void initFocus(int viewWidth, int viewHeight) { mIsSupport = true; mViewWidth = viewWidth; mViewHeight = viewHeight; this.setVisibility(INVISIBLE); mHandler.postDelayed(new Runnable() { @Override public void run() { stopFocus(); } }, 100); measure(MeasureSpec.makeMeasureSpec(mViewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mViewHeight, MeasureSpec.EXACTLY)); requestLayout(); } public void setMotionEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: if (event.getPointerCount() == 1) { if ((event.getX() > mX - mLength / 2 && event.getX() < mX + mLength / 2 && event.getY() > mY - mLength / 2 && event.getY() < mY + mLength / 2)) { mActionState = MotionEvent.ACTION_MOVE; mHandler.removeMessages(IMAGE_DISAPPEAR); mHandler.removeMessages(IMAGE_DISAPPEAR_GOOD); mX = event.getX(); mY = event.getY(); invalidate(); mMoveFollow = true; if (mOnFocusStateChangedListener != null) { mOnFocusStateChangedListener.onBeginMoving(); } } else if (mMoveFollow) { mX = event.getX(); mY = event.getY(); invalidate(); } else { mActionState = STATE_NOTHING; mMoveFollow = false; } } else { mActionState = STATE_2_FINGERS; mMoveFollow = false; } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (event.getPointerCount() == 1 && !mHandler.hasMessages(IMAGE_DISAPPEAR) && !mHandler.hasMessages(IMAGE_DISAPPEAR_GOOD) && mActionState != STATE_2_FINGERS) { if (mOnTriggerFocusListener != null) { mOnTriggerFocusListener.onTriggerFocus(event.getX(), event.getY()); } mX = event.getX(); mY = event.getY(); invalidate(); } else { mActionState = STATE_NOTHING; } mMoveFollow = false; break; } } public void delayDisappear() { if (!mIsSupport) { return; } if (mHandler.hasMessages(IMAGE_DISAPPEAR_GOOD)) { mHandler.removeMessages(IMAGE_DISAPPEAR_GOOD); mHandler.sendEmptyMessageDelayed(IMAGE_DISAPPEAR_GOOD, 400); } if (mHandler.hasMessages(IMAGE_DISAPPEAR)) { mHandler.removeMessages(IMAGE_DISAPPEAR); mHandler.sendEmptyMessageDelayed(IMAGE_DISAPPEAR, 400); } } private OnTriggerFocusListener mOnTriggerFocusListener; public void setOnTriggerFocusListener(OnTriggerFocusListener onTriggerFocusListener) { mOnTriggerFocusListener = onTriggerFocusListener; } public interface OnTriggerFocusListener { void onTriggerFocus(float x, float y); } private OnFocusStateChangedListener mOnFocusStateChangedListener; public void setOnFocusStateChangedListener(OnFocusStateChangedListener onFocusStateChangedListener) { mOnFocusStateChangedListener = onFocusStateChangedListener; } public interface OnFocusStateChangedListener { void onBeginFocusing(float x, float y); void onBeginMoving(); void onFocusDisappeared(); } }