diff --git a/res/drawable-nodpi/fingerprint_sensor_location.png b/res/drawable-nodpi/fingerprint_sensor_location.png
index b95816fb393..587c911baab 100644
Binary files a/res/drawable-nodpi/fingerprint_sensor_location.png and b/res/drawable-nodpi/fingerprint_sensor_location.png differ
diff --git a/res/layout-land/fingerprint_enroll_find_sensor.xml b/res/layout-land/fingerprint_enroll_find_sensor.xml
index 1eaa815dc41..b3401934916 100644
--- a/res/layout-land/fingerprint_enroll_find_sensor.xml
+++ b/res/layout-land/fingerprint_enroll_find_sensor.xml
@@ -58,17 +58,13 @@
+ android:layout_height="match_parent">
-
+
diff --git a/res/layout/fingerprint_enroll_find_sensor_base.xml b/res/layout/fingerprint_enroll_find_sensor_base.xml
index 89b45945bd8..9f1eb4be77a 100644
--- a/res/layout/fingerprint_enroll_find_sensor_base.xml
+++ b/res/layout/fingerprint_enroll_find_sensor_base.xml
@@ -37,15 +37,12 @@
android:layout_marginTop="@dimen/suw_description_margin_top"
android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
-
+ android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
+ android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
+ android:layout_gravity="center_horizontal"/>
+
+
+
+
+
+
+
+
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 858af0e602d..25a7341765e 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -64,6 +64,7 @@
#de000000
#ff009688
#20000000
+ #ff009688
#ff384248
#ff009587
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c2d192d9881..30be6e867b1 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -219,6 +219,11 @@
92dip
4dip
+ 8dp
+ 50dp
+ - 50%
+ - 30%
+ 200dp
- 2.6
0dp
diff --git a/res/values/themes.xml b/res/values/themes.xml
index edba85f42fe..466c6c9738d 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -221,6 +221,7 @@
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index d49fdb621f8..b3a5d2298b4 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -31,6 +31,8 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
private static final int CONFIRM_REQUEST = 1;
private static final int ENROLLING = 2;
+ private FingerprintLocationAnimationView mAnimation;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -39,6 +41,20 @@ public class FingerprintEnrollFindSensor extends FingerprintEnrollBase {
if (mToken == null) {
launchConfirmLock();
}
+ mAnimation = (FingerprintLocationAnimationView) findViewById(
+ R.id.fingerprint_sensor_location_animation);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mAnimation.startAnimation();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mAnimation.stopAnimation();
}
@Override
diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
new file mode 100644
index 00000000000..b52fed31052
--- /dev/null
+++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.fingerprint;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.settings.R;
+
+/**
+ * View which plays an animation to indicate where the sensor is on the device.
+ */
+public class FingerprintLocationAnimationView extends View {
+
+ private static final float MAX_PULSE_ALPHA = 0.15f;
+ private static final long DELAY_BETWEEN_PHASE = 1000;
+
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final Interpolator mFastOutSlowInInterpolator;
+
+ private final int mDotRadius;
+ private final int mMaxPulseRadius;
+ private final float mFractionCenterX;
+ private final float mFractionCenterY;
+ private final Paint mDotPaint = new Paint();
+ private final Paint mPulsePaint = new Paint();
+ private float mPulseRadius;
+ private ValueAnimator mRadiusAnimator;
+ private ValueAnimator mAlphaAnimator;
+
+ public FingerprintLocationAnimationView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ mDotRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_dot_radius);
+ mMaxPulseRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_pulse_radius);
+ mFractionCenterX = getResources().getFraction(
+ R.fraction.fingerprint_sensor_location_fraction_x, 1, 1);
+ mFractionCenterY = getResources().getFraction(
+ R.fraction.fingerprint_sensor_location_fraction_y, 1, 1);
+ int color = getResources().getColor(R.color.fingerprint_dot_color, null);
+ mDotPaint.setAntiAlias(true);
+ mPulsePaint.setAntiAlias(true);
+ mDotPaint.setColor(color);
+ mPulsePaint.setColor(color);
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.linear_out_slow_in);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.linear_out_slow_in);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ drawPulse(canvas);
+ drawDot(canvas);
+ }
+
+ private void drawDot(Canvas canvas) {
+ canvas.drawCircle(getCenterX(), getCenterY(), mDotRadius, mDotPaint);
+ }
+
+ private void drawPulse(Canvas canvas) {
+ canvas.drawCircle(getCenterX(), getCenterY(), mPulseRadius, mPulsePaint);
+ }
+
+ private float getCenterX() {
+ return getWidth() * mFractionCenterX;
+ }
+
+ private float getCenterY() {
+ return getHeight() * mFractionCenterY;
+ }
+
+ public void startAnimation() {
+ startPhase();
+ }
+
+ public void stopAnimation() {
+ removeCallbacks(mStartPhaseRunnable);
+ if (mRadiusAnimator != null) {
+ mRadiusAnimator.cancel();
+ }
+ if (mAlphaAnimator != null) {
+ mAlphaAnimator.cancel();
+ }
+ }
+
+ private void startPhase() {
+ startRadiusAnimation();
+ startAlphaAnimation();
+ }
+
+ private void startRadiusAnimation() {
+ ValueAnimator animator = ValueAnimator.ofFloat(0, mMaxPulseRadius);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mPulseRadius = (float) animation.getAnimatedValue();
+ invalidate();
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+
+ boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mRadiusAnimator = null;
+ if (!mCancelled) {
+ postDelayed(mStartPhaseRunnable, DELAY_BETWEEN_PHASE);
+ }
+ }
+ });
+ animator.setDuration(1000);
+ animator.setInterpolator(mLinearOutSlowInInterpolator);
+ animator.start();
+ mRadiusAnimator = animator;
+ }
+
+ private void startAlphaAnimation() {
+ mPulsePaint.setAlpha((int) (255f * MAX_PULSE_ALPHA));
+ ValueAnimator animator = ValueAnimator.ofFloat(MAX_PULSE_ALPHA, 0f);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mPulsePaint.setAlpha((int) (255f * (float) animation.getAnimatedValue()));
+ invalidate();
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAlphaAnimator = null;
+ }
+ });
+ animator.setDuration(750);
+ animator.setInterpolator(mFastOutSlowInInterpolator);
+ animator.setStartDelay(250);
+ animator.start();
+ mAlphaAnimator = animator;
+ }
+
+ private final Runnable mStartPhaseRunnable = new Runnable() {
+ @Override
+ public void run() {
+ startPhase();
+ }
+ };
+}