Refine fingerprint enrollment experience

- Flash fingerprint graphic when enrollment progresses
- Show hint message when not progressing for a few seconds
- Make sure animation is always working

Bug: 21617091
Bug: 21644138
Change-Id: Ic54c10a655e6da914f960cee20f0066b46d87325
This commit is contained in:
Jorim Jaggi
2015-06-10 15:05:30 -07:00
parent 3f94f562c1
commit 436e02c3d5
10 changed files with 153 additions and 12 deletions

View File

@@ -17,12 +17,15 @@
package com.android.settings.fingerprint;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
@@ -49,6 +52,12 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
private static final int PROGRESS_BAR_MAX = 10000;
private static final int FINISH_DELAY = 250;
/**
* If we don't see progress during this time, we show an error message to remind the user that
* he needs to lift the finger and touch again.
*/
private static final int HINT_TIMEOUT_DURATION = 2500;
/**
* How long the user needs to touch the icon until we show the dialog.
*/
@@ -67,10 +76,15 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
private TextView mRepeatMessage;
private TextView mErrorText;
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
private int mIconTouchCount;
private FingerprintEnrollSidecar mSidecar;
private boolean mAnimationCancelled;
private AnimatedVectorDrawable mIconAnimationDrawable;
private int mIndicatorBackgroundRestingColor;
private int mIndicatorBackgroundActivatedColor;
private boolean mRestoring;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -86,6 +100,10 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.fast_out_slow_in);
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.linear_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.fast_out_linear_in);
mFingerprintAnimator.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -104,6 +122,11 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
return true;
}
});
mIndicatorBackgroundRestingColor
= getColor(R.color.fingerprint_indicator_background_resting);
mIndicatorBackgroundActivatedColor
= getColor(R.color.fingerprint_indicator_background_activated);
mRestoring = savedInstanceState != null;
}
@Override
@@ -117,6 +140,9 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mSidecar.setListener(this);
updateProgress(false /* animate */);
updateDescription();
if (mRestoring) {
startIconAnimation();
}
}
@Override
@@ -158,6 +184,34 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
mProgressAnim = anim;
}
private void animateFlash() {
ValueAnimator anim = ValueAnimator.ofArgb(mIndicatorBackgroundRestingColor,
mIndicatorBackgroundActivatedColor);
final ValueAnimator.AnimatorUpdateListener listener =
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mFingerprintAnimator.setBackgroundTintList(ColorStateList.valueOf(
(Integer) animation.getAnimatedValue()));
}
};
anim.addUpdateListener(listener);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ValueAnimator anim = ValueAnimator.ofArgb(mIndicatorBackgroundActivatedColor,
mIndicatorBackgroundRestingColor);
anim.addUpdateListener(listener);
anim.setDuration(300);
anim.setInterpolator(mLinearOutSlowInInterpolator);
anim.start();
}
});
anim.setInterpolator(mFastOutSlowInInterpolator);
anim.setDuration(300);
anim.start();
}
private void launchFinish(byte[] token) {
Intent intent = new Intent();
intent.setClassName("com.android.settings", FingerprintEnrollFinish.class.getName());
@@ -187,7 +241,7 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
@Override
public void onEnrollmentError(CharSequence errString) {
mErrorText.setText(errString);
showError(errString);
stopIconAnimation();
}
@@ -195,7 +249,10 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
public void onEnrollmentProgressChange(int steps, int remaining) {
updateProgress(true /* animate */);
updateDescription();
mErrorText.setText("");
clearError();
animateFlash();
mErrorText.removeCallbacks(mTouchAgainRunnable);
mErrorText.postDelayed(mTouchAgainRunnable, HINT_TIMEOUT_DURATION);
}
private void updateProgress(boolean animate) {
@@ -221,6 +278,44 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
new IconTouchDialog().show(getFragmentManager(), null /* tag */);
}
private void showError(CharSequence error) {
mErrorText.setText(error);
if (mErrorText.getVisibility() == View.INVISIBLE) {
mErrorText.setVisibility(View.VISIBLE);
mErrorText.setTranslationY(getResources().getDimensionPixelSize(
R.dimen.fingerprint_error_text_appear_distance));
mErrorText.setAlpha(0f);
mErrorText.animate()
.alpha(1f)
.translationY(0f)
.setDuration(200)
.setInterpolator(mLinearOutSlowInInterpolator)
.start();
} else {
mErrorText.animate().cancel();
mErrorText.setAlpha(1f);
mErrorText.setTranslationY(0f);
}
}
private void clearError() {
if (mErrorText.getVisibility() == View.VISIBLE) {
mErrorText.animate()
.alpha(0f)
.translationY(getResources().getDimensionPixelSize(
R.dimen.fingerprint_error_text_disappear_distance))
.setDuration(100)
.setInterpolator(mFastOutLinearInInterpolator)
.withEndAction(new Runnable() {
@Override
public void run() {
mErrorText.setVisibility(View.INVISIBLE);
}
})
.start();
}
}
private final Animator.AnimatorListener mProgressAnimationListener
= new Animator.AnimatorListener() {
@@ -274,6 +369,13 @@ public class FingerprintEnrollEnrolling extends FingerprintEnrollBase
}
};
private final Runnable mTouchAgainRunnable = new Runnable() {
@Override
public void run() {
showError(getString(R.string.security_settings_fingerprint_enroll_lift_touch_again));
}
};
private static class IconTouchDialog extends DialogFragment {
@Override