RESTRICT AUTOMERGE Show tip/edge hints for UDFPS enrollment
Shows visual hints during the tip and edge stages of UDFPS enrollment. Test: Manual Bug: 198858684 Change-Id: Ib2e08fcb7c524916a874932d1b9d558b19028ff0 Merged-In: Ifda20133f1ee90c9e1612e9066c19efbb6ffc9cd Merged-In: Ic12b85bd6f8f1d4068952eb83bcc8a1df21f2e8e
This commit is contained in:
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.biometrics;
|
package com.android.systemui.biometrics;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@@ -26,11 +28,17 @@ import android.graphics.PointF;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.graphics.ColorUtils;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,10 +47,20 @@ import com.android.systemui.R;
|
|||||||
public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
||||||
private static final String TAG = "UdfpsAnimationEnroll";
|
private static final String TAG = "UdfpsAnimationEnroll";
|
||||||
|
|
||||||
private static final long ANIM_DURATION = 800;
|
private static final long HINT_COLOR_ANIM_DELAY_MS = 233L;
|
||||||
|
private static final long HINT_COLOR_ANIM_DURATION_MS = 517L;
|
||||||
|
private static final long HINT_WIDTH_ANIM_DURATION_MS = 233L;
|
||||||
|
private static final long TARGET_ANIM_DURATION_LONG = 800L;
|
||||||
|
private static final long TARGET_ANIM_DURATION_SHORT = 600L;
|
||||||
// 1 + SCALE_MAX is the maximum that the moving target will animate to
|
// 1 + SCALE_MAX is the maximum that the moving target will animate to
|
||||||
private static final float SCALE_MAX = 0.25f;
|
private static final float SCALE_MAX = 0.25f;
|
||||||
|
|
||||||
|
private static final float HINT_PADDING_DP = 10f;
|
||||||
|
private static final float HINT_MAX_WIDTH_DP = 6f;
|
||||||
|
private static final float HINT_ANGLE = 40f;
|
||||||
|
|
||||||
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
@NonNull private final Drawable mMovingTargetFpIcon;
|
@NonNull private final Drawable mMovingTargetFpIcon;
|
||||||
@NonNull private final Paint mSensorOutlinePaint;
|
@NonNull private final Paint mSensorOutlinePaint;
|
||||||
@NonNull private final Paint mBlueFill;
|
@NonNull private final Paint mBlueFill;
|
||||||
@@ -51,17 +69,41 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
@Nullable private UdfpsEnrollHelper mEnrollHelper;
|
@Nullable private UdfpsEnrollHelper mEnrollHelper;
|
||||||
|
|
||||||
// Moving target animator set
|
// Moving target animator set
|
||||||
@Nullable AnimatorSet mAnimatorSet;
|
@Nullable AnimatorSet mTargetAnimatorSet;
|
||||||
// Moving target location
|
// Moving target location
|
||||||
float mCurrentX;
|
float mCurrentX;
|
||||||
float mCurrentY;
|
float mCurrentY;
|
||||||
// Moving target size
|
// Moving target size
|
||||||
float mCurrentScale = 1.f;
|
float mCurrentScale = 1.f;
|
||||||
|
|
||||||
|
@ColorInt private final int mHintColorFaded;
|
||||||
|
@ColorInt private final int mHintColorHighlight;
|
||||||
|
private final float mHintMaxWidthPx;
|
||||||
|
private final float mHintPaddingPx;
|
||||||
|
|
||||||
|
@NonNull private final Animator.AnimatorListener mTargetAnimListener;
|
||||||
|
|
||||||
|
private boolean mShouldShowTipHint = false;
|
||||||
|
@NonNull private final Paint mTipHintPaint;
|
||||||
|
@Nullable private AnimatorSet mTipHintAnimatorSet;
|
||||||
|
@Nullable private ValueAnimator mTipHintColorAnimator;
|
||||||
|
@Nullable private ValueAnimator mTipHintWidthAnimator;
|
||||||
|
@NonNull private final ValueAnimator.AnimatorUpdateListener mTipHintColorUpdateListener;
|
||||||
|
@NonNull private final ValueAnimator.AnimatorUpdateListener mTipHintWidthUpdateListener;
|
||||||
|
@NonNull private final Animator.AnimatorListener mTipHintPulseListener;
|
||||||
|
|
||||||
|
private boolean mShouldShowEdgeHint = false;
|
||||||
|
@NonNull private final Paint mEdgeHintPaint;
|
||||||
|
@Nullable private AnimatorSet mEdgeHintAnimatorSet;
|
||||||
|
@Nullable private ValueAnimator mEdgeHintColorAnimator;
|
||||||
|
@Nullable private ValueAnimator mEdgeHintWidthAnimator;
|
||||||
|
@NonNull private final ValueAnimator.AnimatorUpdateListener mEdgeHintColorUpdateListener;
|
||||||
|
@NonNull private final ValueAnimator.AnimatorUpdateListener mEdgeHintWidthUpdateListener;
|
||||||
|
@NonNull private final Animator.AnimatorListener mEdgeHintPulseListener;
|
||||||
|
|
||||||
UdfpsEnrollDrawable(@NonNull Context context) {
|
UdfpsEnrollDrawable(@NonNull Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
|
|
||||||
mSensorOutlinePaint = new Paint(0 /* flags */);
|
mSensorOutlinePaint = new Paint(0 /* flags */);
|
||||||
mSensorOutlinePaint.setAntiAlias(true);
|
mSensorOutlinePaint.setAntiAlias(true);
|
||||||
mSensorOutlinePaint.setColor(mContext.getColor(R.color.udfps_enroll_icon));
|
mSensorOutlinePaint.setColor(mContext.getColor(R.color.udfps_enroll_icon));
|
||||||
@@ -78,6 +120,117 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
mMovingTargetFpIcon.mutate();
|
mMovingTargetFpIcon.mutate();
|
||||||
|
|
||||||
mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
|
mFingerprintDrawable.setTint(mContext.getColor(R.color.udfps_enroll_icon));
|
||||||
|
|
||||||
|
mHintColorFaded = getHintColorFaded(context);
|
||||||
|
mHintColorHighlight = context.getColor(R.color.udfps_enroll_progress);
|
||||||
|
mHintMaxWidthPx = Utils.dpToPixels(context, HINT_MAX_WIDTH_DP);
|
||||||
|
mHintPaddingPx = Utils.dpToPixels(context, HINT_PADDING_DP);
|
||||||
|
|
||||||
|
mTargetAnimListener = new Animator.AnimatorListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
updateTipHintVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
mTipHintPaint = new Paint(0 /* flags */);
|
||||||
|
mTipHintPaint.setAntiAlias(true);
|
||||||
|
mTipHintPaint.setColor(mHintColorFaded);
|
||||||
|
mTipHintPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mTipHintPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
mTipHintPaint.setStrokeWidth(0f);
|
||||||
|
mTipHintColorUpdateListener = animation -> {
|
||||||
|
mTipHintPaint.setColor((int) animation.getAnimatedValue());
|
||||||
|
invalidateSelf();
|
||||||
|
};
|
||||||
|
mTipHintWidthUpdateListener = animation -> {
|
||||||
|
mTipHintPaint.setStrokeWidth((float) animation.getAnimatedValue());
|
||||||
|
invalidateSelf();
|
||||||
|
};
|
||||||
|
mTipHintPulseListener = new Animator.AnimatorListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
mHandler.postDelayed(() -> {
|
||||||
|
mTipHintColorAnimator =
|
||||||
|
ValueAnimator.ofArgb(mTipHintPaint.getColor(), mHintColorFaded);
|
||||||
|
mTipHintColorAnimator.setInterpolator(new LinearInterpolator());
|
||||||
|
mTipHintColorAnimator.setDuration(HINT_COLOR_ANIM_DURATION_MS);
|
||||||
|
mTipHintColorAnimator.addUpdateListener(mTipHintColorUpdateListener);
|
||||||
|
mTipHintColorAnimator.start();
|
||||||
|
}, HINT_COLOR_ANIM_DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
mEdgeHintPaint = new Paint(0 /* flags */);
|
||||||
|
mEdgeHintPaint.setAntiAlias(true);
|
||||||
|
mEdgeHintPaint.setColor(mHintColorFaded);
|
||||||
|
mEdgeHintPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mEdgeHintPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
mEdgeHintPaint.setStrokeWidth(0f);
|
||||||
|
mEdgeHintColorUpdateListener = animation -> {
|
||||||
|
mEdgeHintPaint.setColor((int) animation.getAnimatedValue());
|
||||||
|
invalidateSelf();
|
||||||
|
};
|
||||||
|
mEdgeHintWidthUpdateListener = animation -> {
|
||||||
|
mEdgeHintPaint.setStrokeWidth((float) animation.getAnimatedValue());
|
||||||
|
invalidateSelf();
|
||||||
|
};
|
||||||
|
mEdgeHintPulseListener = new Animator.AnimatorListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
mHandler.postDelayed(() -> {
|
||||||
|
mEdgeHintColorAnimator =
|
||||||
|
ValueAnimator.ofArgb(mEdgeHintPaint.getColor(), mHintColorFaded);
|
||||||
|
mEdgeHintColorAnimator.setInterpolator(new LinearInterpolator());
|
||||||
|
mEdgeHintColorAnimator.setDuration(HINT_COLOR_ANIM_DURATION_MS);
|
||||||
|
mEdgeHintColorAnimator.addUpdateListener(mEdgeHintColorUpdateListener);
|
||||||
|
mEdgeHintColorAnimator.start();
|
||||||
|
}, HINT_COLOR_ANIM_DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@ColorInt
|
||||||
|
private static int getHintColorFaded(@NonNull Context context) {
|
||||||
|
final TypedValue tv = new TypedValue();
|
||||||
|
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, tv, true);
|
||||||
|
final int alpha = (int) (tv.getFloat() * 255f);
|
||||||
|
|
||||||
|
final int[] attrs = new int[] {android.R.attr.colorControlNormal};
|
||||||
|
final TypedArray ta = context.obtainStyledAttributes(attrs);
|
||||||
|
try {
|
||||||
|
@ColorInt final int color = ta.getColor(0, context.getColor(R.color.white_disabled));
|
||||||
|
return ColorUtils.setAlphaComponent(color, alpha);
|
||||||
|
} finally {
|
||||||
|
ta.recycle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnrollHelper(@NonNull UdfpsEnrollHelper helper) {
|
void setEnrollHelper(@NonNull UdfpsEnrollHelper helper) {
|
||||||
@@ -98,9 +251,13 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onEnrollmentProgress(int remaining, int totalSteps) {
|
void onEnrollmentProgress(int remaining, int totalSteps) {
|
||||||
if (mEnrollHelper != null && !mEnrollHelper.isCenterEnrollmentStage()) {
|
if (mEnrollHelper == null) {
|
||||||
if (mAnimatorSet != null && mAnimatorSet.isRunning()) {
|
return;
|
||||||
mAnimatorSet.end();
|
}
|
||||||
|
|
||||||
|
if (!mEnrollHelper.isCenterEnrollmentStage()) {
|
||||||
|
if (mTargetAnimatorSet != null && mTargetAnimatorSet.isRunning()) {
|
||||||
|
mTargetAnimatorSet.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
final PointF point = mEnrollHelper.getNextGuidedEnrollmentPoint();
|
final PointF point = mEnrollHelper.getNextGuidedEnrollmentPoint();
|
||||||
@@ -117,8 +274,13 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
invalidateSelf();
|
invalidateSelf();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final boolean isMovingToCenter = point.x == 0f && point.y == 0f;
|
||||||
|
final long duration = isMovingToCenter
|
||||||
|
? TARGET_ANIM_DURATION_SHORT
|
||||||
|
: TARGET_ANIM_DURATION_LONG;
|
||||||
|
|
||||||
final ValueAnimator scale = ValueAnimator.ofFloat(0, (float) Math.PI);
|
final ValueAnimator scale = ValueAnimator.ofFloat(0, (float) Math.PI);
|
||||||
scale.setDuration(ANIM_DURATION);
|
scale.setDuration(duration);
|
||||||
scale.addUpdateListener(animation -> {
|
scale.addUpdateListener(animation -> {
|
||||||
// Grow then shrink
|
// Grow then shrink
|
||||||
mCurrentScale = 1
|
mCurrentScale = 1
|
||||||
@@ -126,14 +288,117 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
invalidateSelf();
|
invalidateSelf();
|
||||||
});
|
});
|
||||||
|
|
||||||
mAnimatorSet = new AnimatorSet();
|
mTargetAnimatorSet = new AnimatorSet();
|
||||||
|
|
||||||
mAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
|
mTargetAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||||
mAnimatorSet.setDuration(ANIM_DURATION);
|
mTargetAnimatorSet.setDuration(duration);
|
||||||
mAnimatorSet.playTogether(x, y, scale);
|
mTargetAnimatorSet.addListener(mTargetAnimListener);
|
||||||
mAnimatorSet.start();
|
mTargetAnimatorSet.playTogether(x, y, scale);
|
||||||
|
mTargetAnimatorSet.start();
|
||||||
|
} else {
|
||||||
|
updateTipHintVisibility();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateTipHintVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateEdgeHintVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTipHintVisibility() {
|
||||||
|
final boolean shouldShow = mEnrollHelper != null && mEnrollHelper.isTipEnrollmentStage();
|
||||||
|
if (mShouldShowTipHint == shouldShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mShouldShowTipHint = shouldShow;
|
||||||
|
|
||||||
|
if (mTipHintWidthAnimator != null && mTipHintWidthAnimator.isRunning()) {
|
||||||
|
mTipHintWidthAnimator.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
final float targetWidth = shouldShow ? mHintMaxWidthPx : 0f;
|
||||||
|
mTipHintWidthAnimator = ValueAnimator.ofFloat(mTipHintPaint.getStrokeWidth(), targetWidth);
|
||||||
|
mTipHintWidthAnimator.setDuration(HINT_WIDTH_ANIM_DURATION_MS);
|
||||||
|
mTipHintWidthAnimator.addUpdateListener(mTipHintWidthUpdateListener);
|
||||||
|
|
||||||
|
if (shouldShow) {
|
||||||
|
startTipHintPulseAnimation();
|
||||||
|
} else {
|
||||||
|
mTipHintWidthAnimator.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateEdgeHintVisibility() {
|
||||||
|
final boolean shouldShow = mEnrollHelper != null && mEnrollHelper.isEdgeEnrollmentStage();
|
||||||
|
if (mShouldShowEdgeHint == shouldShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mShouldShowEdgeHint = shouldShow;
|
||||||
|
|
||||||
|
if (mEdgeHintWidthAnimator != null && mEdgeHintWidthAnimator.isRunning()) {
|
||||||
|
mEdgeHintWidthAnimator.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
final float targetWidth = shouldShow ? mHintMaxWidthPx : 0f;
|
||||||
|
mEdgeHintWidthAnimator =
|
||||||
|
ValueAnimator.ofFloat(mEdgeHintPaint.getStrokeWidth(), targetWidth);
|
||||||
|
mEdgeHintWidthAnimator.setDuration(HINT_WIDTH_ANIM_DURATION_MS);
|
||||||
|
mEdgeHintWidthAnimator.addUpdateListener(mEdgeHintWidthUpdateListener);
|
||||||
|
|
||||||
|
if (shouldShow) {
|
||||||
|
startEdgeHintPulseAnimation();
|
||||||
|
} else {
|
||||||
|
mEdgeHintWidthAnimator.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startTipHintPulseAnimation() {
|
||||||
|
mHandler.removeCallbacksAndMessages(null);
|
||||||
|
if (mTipHintAnimatorSet != null && mTipHintAnimatorSet.isRunning()) {
|
||||||
|
mTipHintAnimatorSet.cancel();
|
||||||
|
}
|
||||||
|
if (mTipHintColorAnimator != null && mTipHintColorAnimator.isRunning()) {
|
||||||
|
mTipHintColorAnimator.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
mTipHintColorAnimator = ValueAnimator.ofArgb(mTipHintPaint.getColor(), mHintColorHighlight);
|
||||||
|
mTipHintColorAnimator.setDuration(HINT_WIDTH_ANIM_DURATION_MS);
|
||||||
|
mTipHintColorAnimator.addUpdateListener(mTipHintColorUpdateListener);
|
||||||
|
mTipHintColorAnimator.addListener(mTipHintPulseListener);
|
||||||
|
|
||||||
|
mTipHintAnimatorSet = new AnimatorSet();
|
||||||
|
mTipHintAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||||
|
mTipHintAnimatorSet.playTogether(mTipHintColorAnimator, mTipHintWidthAnimator);
|
||||||
|
mTipHintAnimatorSet.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startEdgeHintPulseAnimation() {
|
||||||
|
mHandler.removeCallbacksAndMessages(null);
|
||||||
|
if (mEdgeHintAnimatorSet != null && mEdgeHintAnimatorSet.isRunning()) {
|
||||||
|
mEdgeHintAnimatorSet.cancel();
|
||||||
|
}
|
||||||
|
if (mEdgeHintColorAnimator != null && mEdgeHintColorAnimator.isRunning()) {
|
||||||
|
mEdgeHintColorAnimator.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
mEdgeHintColorAnimator =
|
||||||
|
ValueAnimator.ofArgb(mEdgeHintPaint.getColor(), mHintColorHighlight);
|
||||||
|
mEdgeHintColorAnimator.setDuration(HINT_WIDTH_ANIM_DURATION_MS);
|
||||||
|
mEdgeHintColorAnimator.addUpdateListener(mEdgeHintColorUpdateListener);
|
||||||
|
mEdgeHintColorAnimator.addListener(mEdgeHintPulseListener);
|
||||||
|
|
||||||
|
mEdgeHintAnimatorSet = new AnimatorSet();
|
||||||
|
mEdgeHintAnimatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
|
||||||
|
mEdgeHintAnimatorSet.playTogether(mEdgeHintColorAnimator, mEdgeHintWidthAnimator);
|
||||||
|
mEdgeHintAnimatorSet.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTipHintVisible() {
|
||||||
|
return mTipHintPaint.getStrokeWidth() > 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEdgeHintVisible() {
|
||||||
|
return mEdgeHintPaint.getStrokeWidth() > 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -163,6 +428,59 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable {
|
|||||||
mFingerprintDrawable.setAlpha(mAlpha);
|
mFingerprintDrawable.setAlpha(mAlpha);
|
||||||
mSensorOutlinePaint.setAlpha(mAlpha);
|
mSensorOutlinePaint.setAlpha(mAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw the finger tip or edges hint.
|
||||||
|
if (isTipHintVisible() || isEdgeHintVisible()) {
|
||||||
|
canvas.save();
|
||||||
|
|
||||||
|
// Make arcs start from the top, rather than the right.
|
||||||
|
canvas.rotate(-90f, mSensorRect.centerX(), mSensorRect.centerY());
|
||||||
|
|
||||||
|
final float halfSensorHeight = Math.abs(mSensorRect.bottom - mSensorRect.top) / 2f;
|
||||||
|
final float halfSensorWidth = Math.abs(mSensorRect.right - mSensorRect.left) / 2f;
|
||||||
|
final float hintXOffset = halfSensorWidth + mHintPaddingPx;
|
||||||
|
final float hintYOffset = halfSensorHeight + mHintPaddingPx;
|
||||||
|
|
||||||
|
if (isTipHintVisible()) {
|
||||||
|
canvas.drawArc(
|
||||||
|
mSensorRect.centerX() - hintXOffset,
|
||||||
|
mSensorRect.centerY() - hintYOffset,
|
||||||
|
mSensorRect.centerX() + hintXOffset,
|
||||||
|
mSensorRect.centerY() + hintYOffset,
|
||||||
|
-HINT_ANGLE / 2f,
|
||||||
|
HINT_ANGLE,
|
||||||
|
false /* useCenter */,
|
||||||
|
mTipHintPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEdgeHintVisible()) {
|
||||||
|
// Draw right edge hint.
|
||||||
|
canvas.rotate(-90f, mSensorRect.centerX(), mSensorRect.centerY());
|
||||||
|
canvas.drawArc(
|
||||||
|
mSensorRect.centerX() - hintXOffset,
|
||||||
|
mSensorRect.centerY() - hintYOffset,
|
||||||
|
mSensorRect.centerX() + hintXOffset,
|
||||||
|
mSensorRect.centerY() + hintYOffset,
|
||||||
|
-HINT_ANGLE / 2f,
|
||||||
|
HINT_ANGLE,
|
||||||
|
false /* useCenter */,
|
||||||
|
mEdgeHintPaint);
|
||||||
|
|
||||||
|
// Draw left edge hint.
|
||||||
|
canvas.rotate(180f, mSensorRect.centerX(), mSensorRect.centerY());
|
||||||
|
canvas.drawArc(
|
||||||
|
mSensorRect.centerX() - hintXOffset,
|
||||||
|
mSensorRect.centerY() - hintYOffset,
|
||||||
|
mSensorRect.centerX() + hintXOffset,
|
||||||
|
mSensorRect.centerY() + hintYOffset,
|
||||||
|
-HINT_ANGLE / 2f,
|
||||||
|
HINT_ANGLE,
|
||||||
|
false /* useCenter */,
|
||||||
|
mEdgeHintPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -202,6 +202,21 @@ public class UdfpsEnrollHelper {
|
|||||||
return progressSteps >= STAGE_THRESHOLDS[0] && progressSteps < STAGE_THRESHOLDS[1];
|
return progressSteps >= STAGE_THRESHOLDS[0] && progressSteps < STAGE_THRESHOLDS[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isTipEnrollmentStage() {
|
||||||
|
if (mTotalSteps == -1 || mRemainingSteps == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final int progressSteps = mTotalSteps - mRemainingSteps;
|
||||||
|
return progressSteps >= STAGE_THRESHOLDS[1] && progressSteps < STAGE_THRESHOLDS[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isEdgeEnrollmentStage() {
|
||||||
|
if (mTotalSteps == -1 || mRemainingSteps == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return mTotalSteps - mRemainingSteps >= STAGE_THRESHOLDS[2];
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
PointF getNextGuidedEnrollmentPoint() {
|
PointF getNextGuidedEnrollmentPoint() {
|
||||||
if (mAccessibilityEnabled || !isGuidedEnrollmentStage()) {
|
if (mAccessibilityEnabled || !isGuidedEnrollmentStage()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user