• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.settings.fingerprint;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.ValueAnimator;
22 import android.annotation.ColorInt;
23 import android.annotation.Nullable;
24 import android.content.Context;
25 import android.graphics.Canvas;
26 import android.graphics.Paint;
27 import android.util.AttributeSet;
28 import android.view.View;
29 import android.view.animation.AnimationUtils;
30 import android.view.animation.Interpolator;
31 
32 import com.android.settings.R;
33 import com.android.settings.Utils;
34 
35 /**
36  * View which plays an animation to indicate where the sensor is on the device.
37  */
38 public class FingerprintLocationAnimationView extends View implements
39         FingerprintFindSensorAnimation {
40 
41     private static final float MAX_PULSE_ALPHA = 0.15f;
42     private static final long DELAY_BETWEEN_PHASE = 1000;
43 
44     private final Interpolator mLinearOutSlowInInterpolator;
45     private final Interpolator mFastOutSlowInInterpolator;
46 
47     private final int mDotRadius;
48     private final int mMaxPulseRadius;
49     private final float mFractionCenterX;
50     private final float mFractionCenterY;
51     private final Paint mDotPaint = new Paint();
52     private final Paint mPulsePaint = new Paint();
53     private float mPulseRadius;
54     private ValueAnimator mRadiusAnimator;
55     private ValueAnimator mAlphaAnimator;
56 
FingerprintLocationAnimationView(Context context, @Nullable AttributeSet attrs)57     public FingerprintLocationAnimationView(Context context, @Nullable AttributeSet attrs) {
58         super(context, attrs);
59         mDotRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_dot_radius);
60         mMaxPulseRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_pulse_radius);
61         mFractionCenterX = getResources().getFraction(
62                 R.fraction.fingerprint_sensor_location_fraction_x, 1, 1);
63         mFractionCenterY = getResources().getFraction(
64                 R.fraction.fingerprint_sensor_location_fraction_y, 1, 1);
65         @ColorInt int colorAccent = Utils.getColorAccent(context);
66         mDotPaint.setAntiAlias(true);
67         mPulsePaint.setAntiAlias(true);
68         mDotPaint.setColor(colorAccent);
69         mPulsePaint.setColor(colorAccent);
70         mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
71                 android.R.interpolator.linear_out_slow_in);
72         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
73                 android.R.interpolator.linear_out_slow_in);
74     }
75 
76     @Override
onDraw(Canvas canvas)77     protected void onDraw(Canvas canvas) {
78         drawPulse(canvas);
79         drawDot(canvas);
80     }
81 
drawDot(Canvas canvas)82     private void drawDot(Canvas canvas) {
83         canvas.drawCircle(getCenterX(), getCenterY(), mDotRadius, mDotPaint);
84     }
85 
drawPulse(Canvas canvas)86     private void drawPulse(Canvas canvas) {
87         canvas.drawCircle(getCenterX(), getCenterY(), mPulseRadius, mPulsePaint);
88     }
89 
getCenterX()90     private float getCenterX() {
91         return getWidth() * mFractionCenterX;
92     }
93 
getCenterY()94     private float getCenterY() {
95         return getHeight() * mFractionCenterY;
96     }
97 
98     @Override
startAnimation()99     public void startAnimation() {
100         startPhase();
101     }
102 
103     @Override
stopAnimation()104     public void stopAnimation() {
105         removeCallbacks(mStartPhaseRunnable);
106         if (mRadiusAnimator != null) {
107             mRadiusAnimator.cancel();
108         }
109         if (mAlphaAnimator != null) {
110             mAlphaAnimator.cancel();
111         }
112     }
113 
114     @Override
pauseAnimation()115     public void pauseAnimation() {
116         stopAnimation();
117     }
118 
startPhase()119     private void startPhase() {
120         startRadiusAnimation();
121         startAlphaAnimation();
122     }
123 
startRadiusAnimation()124     private void startRadiusAnimation() {
125         ValueAnimator animator = ValueAnimator.ofFloat(0, mMaxPulseRadius);
126         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
127             @Override
128             public void onAnimationUpdate(ValueAnimator animation) {
129                 mPulseRadius = (float) animation.getAnimatedValue();
130                 invalidate();
131             }
132         });
133         animator.addListener(new AnimatorListenerAdapter() {
134 
135             boolean mCancelled;
136 
137             @Override
138             public void onAnimationCancel(Animator animation) {
139                 mCancelled = true;
140             }
141 
142             @Override
143             public void onAnimationEnd(Animator animation) {
144                 mRadiusAnimator = null;
145                 if (!mCancelled) {
146                     postDelayed(mStartPhaseRunnable, DELAY_BETWEEN_PHASE);
147                 }
148             }
149         });
150         animator.setDuration(1000);
151         animator.setInterpolator(mLinearOutSlowInInterpolator);
152         animator.start();
153         mRadiusAnimator = animator;
154     }
155 
startAlphaAnimation()156     private void startAlphaAnimation() {
157         mPulsePaint.setAlpha((int) (255f * MAX_PULSE_ALPHA));
158         ValueAnimator animator = ValueAnimator.ofFloat(MAX_PULSE_ALPHA, 0f);
159         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
160             @Override
161             public void onAnimationUpdate(ValueAnimator animation) {
162                 mPulsePaint.setAlpha((int) (255f * (float) animation.getAnimatedValue()));
163                 invalidate();
164             }
165         });
166         animator.addListener(new AnimatorListenerAdapter() {
167             @Override
168             public void onAnimationEnd(Animator animation) {
169                 mAlphaAnimator = null;
170             }
171         });
172         animator.setDuration(750);
173         animator.setInterpolator(mFastOutSlowInInterpolator);
174         animator.setStartDelay(250);
175         animator.start();
176         mAlphaAnimator = animator;
177     }
178 
179     private final Runnable mStartPhaseRunnable = new Runnable() {
180         @Override
181         public void run() {
182             startPhase();
183         }
184     };
185 }
186