• 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.Nullable;
23 import android.content.Context;
24 import android.graphics.Canvas;
25 import android.graphics.Paint;
26 import android.util.AttributeSet;
27 import android.util.TypedValue;
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 
34 /**
35  * View which plays an animation to indicate where the sensor is on the device.
36  */
37 public class FingerprintLocationAnimationView extends View implements
38         FingerprintFindSensorAnimation {
39 
40     private static final float MAX_PULSE_ALPHA = 0.15f;
41     private static final long DELAY_BETWEEN_PHASE = 1000;
42 
43     private final Interpolator mLinearOutSlowInInterpolator;
44     private final Interpolator mFastOutSlowInInterpolator;
45 
46     private final int mDotRadius;
47     private final int mMaxPulseRadius;
48     private final float mFractionCenterX;
49     private final float mFractionCenterY;
50     private final Paint mDotPaint = new Paint();
51     private final Paint mPulsePaint = new Paint();
52     private float mPulseRadius;
53     private ValueAnimator mRadiusAnimator;
54     private ValueAnimator mAlphaAnimator;
55 
FingerprintLocationAnimationView(Context context, @Nullable AttributeSet attrs)56     public FingerprintLocationAnimationView(Context context, @Nullable AttributeSet attrs) {
57         super(context, attrs);
58         mDotRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_dot_radius);
59         mMaxPulseRadius = getResources().getDimensionPixelSize(R.dimen.fingerprint_pulse_radius);
60         mFractionCenterX = getResources().getFraction(
61                 R.fraction.fingerprint_sensor_location_fraction_x, 1, 1);
62         mFractionCenterY = getResources().getFraction(
63                 R.fraction.fingerprint_sensor_location_fraction_y, 1, 1);
64         TypedValue typedValue = new TypedValue();
65         context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
66         int color = getResources().getColor(typedValue.resourceId, null);
67         mDotPaint.setAntiAlias(true);
68         mPulsePaint.setAntiAlias(true);
69         mDotPaint.setColor(color);
70         mPulsePaint.setColor(color);
71         mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
72                 android.R.interpolator.linear_out_slow_in);
73         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
74                 android.R.interpolator.linear_out_slow_in);
75     }
76 
77     @Override
onDraw(Canvas canvas)78     protected void onDraw(Canvas canvas) {
79         drawPulse(canvas);
80         drawDot(canvas);
81     }
82 
drawDot(Canvas canvas)83     private void drawDot(Canvas canvas) {
84         canvas.drawCircle(getCenterX(), getCenterY(), mDotRadius, mDotPaint);
85     }
86 
drawPulse(Canvas canvas)87     private void drawPulse(Canvas canvas) {
88         canvas.drawCircle(getCenterX(), getCenterY(), mPulseRadius, mPulsePaint);
89     }
90 
getCenterX()91     private float getCenterX() {
92         return getWidth() * mFractionCenterX;
93     }
94 
getCenterY()95     private float getCenterY() {
96         return getHeight() * mFractionCenterY;
97     }
98 
99     @Override
startAnimation()100     public void startAnimation() {
101         startPhase();
102     }
103 
104     @Override
stopAnimation()105     public void stopAnimation() {
106         removeCallbacks(mStartPhaseRunnable);
107         if (mRadiusAnimator != null) {
108             mRadiusAnimator.cancel();
109         }
110         if (mAlphaAnimator != null) {
111             mAlphaAnimator.cancel();
112         }
113     }
114 
115     @Override
pauseAnimation()116     public void pauseAnimation() {
117         stopAnimation();
118     }
119 
startPhase()120     private void startPhase() {
121         startRadiusAnimation();
122         startAlphaAnimation();
123     }
124 
startRadiusAnimation()125     private void startRadiusAnimation() {
126         ValueAnimator animator = ValueAnimator.ofFloat(0, mMaxPulseRadius);
127         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
128             @Override
129             public void onAnimationUpdate(ValueAnimator animation) {
130                 mPulseRadius = (float) animation.getAnimatedValue();
131                 invalidate();
132             }
133         });
134         animator.addListener(new AnimatorListenerAdapter() {
135 
136             boolean mCancelled;
137 
138             @Override
139             public void onAnimationCancel(Animator animation) {
140                 mCancelled = true;
141             }
142 
143             @Override
144             public void onAnimationEnd(Animator animation) {
145                 mRadiusAnimator = null;
146                 if (!mCancelled) {
147                     postDelayed(mStartPhaseRunnable, DELAY_BETWEEN_PHASE);
148                 }
149             }
150         });
151         animator.setDuration(1000);
152         animator.setInterpolator(mLinearOutSlowInInterpolator);
153         animator.start();
154         mRadiusAnimator = animator;
155     }
156 
startAlphaAnimation()157     private void startAlphaAnimation() {
158         mPulsePaint.setAlpha((int) (255f * MAX_PULSE_ALPHA));
159         ValueAnimator animator = ValueAnimator.ofFloat(MAX_PULSE_ALPHA, 0f);
160         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
161             @Override
162             public void onAnimationUpdate(ValueAnimator animation) {
163                 mPulsePaint.setAlpha((int) (255f * (float) animation.getAnimatedValue()));
164                 invalidate();
165             }
166         });
167         animator.addListener(new AnimatorListenerAdapter() {
168             @Override
169             public void onAnimationEnd(Animator animation) {
170                 mAlphaAnimator = null;
171             }
172         });
173         animator.setDuration(750);
174         animator.setInterpolator(mFastOutSlowInInterpolator);
175         animator.setStartDelay(250);
176         animator.start();
177         mAlphaAnimator = animator;
178     }
179 
180     private final Runnable mStartPhaseRunnable = new Runnable() {
181         @Override
182         public void run() {
183             startPhase();
184         }
185     };
186 }
187