Implement trust managed visuals
Updates the trust managed indicator to match the speced visuals and behavior. Bug: 15519687 Change-Id: I2be04e8b37f3b5d9865ae4d25b46222cafadd113
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright (C) 2014 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
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring"
|
||||
android:innerRadius="22dp" android:thickness="2dp">
|
||||
<solid android:color="#4cffffff" />
|
||||
</shape>
|
||||
@@ -430,4 +430,16 @@
|
||||
|
||||
<!-- The text size for battery level -->
|
||||
<dimen name="battery_level_text_size">12sp</dimen>
|
||||
|
||||
<!-- TrustDrawable: Minimum inner radius of the breathing animation -->
|
||||
<dimen name="trust_circle_inner_radius_visible_min">22dp</dimen>
|
||||
<!-- TrustDrawable: Maximum inner radius of the breathing animation -->
|
||||
<dimen name="trust_circle_inner_radius_visible_max">24dp</dimen>
|
||||
<!-- TrustDrawable: Inner radius at the end of the exit animation -->
|
||||
<dimen name="trust_circle_inner_radius_exit">38dp</dimen>
|
||||
<!-- TrustDrawable: Inner radius at the beginning of the enter animation -->
|
||||
<dimen name="trust_circle_inner_radius_enter">18dp</dimen>
|
||||
<!-- TrustDrawable: Thickness of the circle -->
|
||||
<dimen name="trust_circle_thickness">2dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -82,21 +82,24 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
private KeyguardIndicationController mIndicationController;
|
||||
private boolean mFaceUnlockRunning;
|
||||
|
||||
private final TrustDrawable mTrustDrawable;
|
||||
|
||||
public KeyguardBottomAreaView(Context context) {
|
||||
super(context);
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
mTrustDrawable = new TrustDrawable(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -120,6 +123,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
|
||||
inflatePreviews();
|
||||
mLockIcon.setOnClickListener(this);
|
||||
mLockIcon.setBackground(mTrustDrawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,14 +271,31 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
@Override
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
if (isShown()) {
|
||||
mTrustDrawable.start();
|
||||
} else {
|
||||
mTrustDrawable.stop();
|
||||
}
|
||||
if (changedView == this && visibility == VISIBLE) {
|
||||
updateLockIcon();
|
||||
updateCameraVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mTrustDrawable.stop();
|
||||
}
|
||||
|
||||
private void updateLockIcon() {
|
||||
if (getVisibility() != VISIBLE) {
|
||||
boolean visible = isShown() && KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
|
||||
if (visible) {
|
||||
mTrustDrawable.start();
|
||||
} else {
|
||||
mTrustDrawable.stop();
|
||||
}
|
||||
if (!visible) {
|
||||
return;
|
||||
}
|
||||
// TODO: Real icon for facelock.
|
||||
@@ -283,11 +304,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
: R.drawable.ic_lock_24dp;
|
||||
mLockIcon.setImageResource(iconRes);
|
||||
boolean trustManaged = mUnlockMethodCache.isTrustManaged();
|
||||
mLockIcon.setBackgroundResource(trustManaged && !mFaceUnlockRunning
|
||||
? R.drawable.trust_circle : 0);
|
||||
mTrustDrawable.setTrustManaged(trustManaged);
|
||||
mLockIcon.setClickable(trustManaged);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public KeyguardAffordanceView getPhoneView() {
|
||||
return mPhoneImageView;
|
||||
}
|
||||
@@ -359,6 +381,16 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mFaceUnlockRunning = running;
|
||||
updateLockIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenTurnedOn() {
|
||||
updateLockIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenTurnedOff(int why) {
|
||||
updateLockIcon();
|
||||
}
|
||||
};
|
||||
|
||||
public void setKeyguardIndicationController(
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.systemui.statusbar.phone;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
public class TrustDrawable extends Drawable {
|
||||
|
||||
private static final long ENTERING_FROM_UNSET_START_DELAY = 200;
|
||||
private static final long VISIBLE_DURATION = 1000;
|
||||
private static final long EXIT_DURATION = 500;
|
||||
private static final long ENTER_DURATION = 500;
|
||||
|
||||
private static final int ALPHA_VISIBLE_MIN = 0x26;
|
||||
private static final int ALPHA_VISIBLE_MAX = 0x4c;
|
||||
|
||||
private static final int STATE_UNSET = -1;
|
||||
private static final int STATE_GONE = 0;
|
||||
private static final int STATE_ENTERING = 1;
|
||||
private static final int STATE_VISIBLE = 2;
|
||||
private static final int STATE_EXITING = 3;
|
||||
|
||||
private int mAlpha;
|
||||
private boolean mAnimating;
|
||||
|
||||
private int mCurAlpha;
|
||||
private float mCurInnerRadius;
|
||||
private Animator mCurAnimator;
|
||||
private int mState = STATE_UNSET;
|
||||
private Paint mPaint;
|
||||
private boolean mTrustManaged;
|
||||
|
||||
private final float mInnerRadiusVisibleMin;
|
||||
private final float mInnerRadiusVisibleMax;
|
||||
private final float mInnerRadiusExit;
|
||||
private final float mInnerRadiusEnter;
|
||||
private final float mThickness;
|
||||
|
||||
private final Animator mVisibleAnimator;
|
||||
|
||||
private final Interpolator mLinearOutSlowInInterpolator;
|
||||
private final Interpolator mFastOutSlowInInterpolator;
|
||||
private final Interpolator mAccelerateDecelerateInterpolator;
|
||||
|
||||
public TrustDrawable(Context context) {
|
||||
Resources r = context.getResources();
|
||||
mInnerRadiusVisibleMin = r.getDimension(R.dimen.trust_circle_inner_radius_visible_min);
|
||||
mInnerRadiusVisibleMax = r.getDimension(R.dimen.trust_circle_inner_radius_visible_max);
|
||||
mInnerRadiusExit = r.getDimension(R.dimen.trust_circle_inner_radius_exit);
|
||||
mInnerRadiusEnter = r.getDimension(R.dimen.trust_circle_inner_radius_enter);
|
||||
mThickness = r.getDimension(R.dimen.trust_circle_thickness);
|
||||
|
||||
mCurInnerRadius = mInnerRadiusEnter;
|
||||
|
||||
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||
context, android.R.interpolator.linear_out_slow_in);
|
||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||
context, android.R.interpolator.fast_out_slow_in);
|
||||
mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
|
||||
|
||||
mVisibleAnimator = makeVisibleAnimator();
|
||||
|
||||
mPaint = new Paint();
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setColor(Color.WHITE);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStrokeWidth(mThickness);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int newAlpha = (mCurAlpha * mAlpha) / 256;
|
||||
if (newAlpha == 0) {
|
||||
return;
|
||||
}
|
||||
final Rect r = getBounds();
|
||||
mPaint.setAlpha(newAlpha);
|
||||
canvas.drawCircle(r.exactCenterX(), r.exactCenterY(), mCurInnerRadius, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mAlpha = alpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
throw new UnsupportedOperationException("not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (!mAnimating) {
|
||||
mAnimating = true;
|
||||
updateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (mAnimating) {
|
||||
mAnimating = false;
|
||||
if (mCurAnimator != null) {
|
||||
mCurAnimator.cancel();
|
||||
mCurAnimator = null;
|
||||
}
|
||||
mState = STATE_UNSET;
|
||||
mCurAlpha = 0;
|
||||
mCurInnerRadius = mInnerRadiusEnter;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTrustManaged(boolean trustManaged) {
|
||||
if (trustManaged == mTrustManaged && mState != STATE_UNSET) return;
|
||||
mTrustManaged = trustManaged;
|
||||
if (mAnimating) {
|
||||
updateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateState(boolean animate) {
|
||||
int nextState = mState;
|
||||
if (mState == STATE_UNSET) {
|
||||
nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE;
|
||||
} else if (mState == STATE_GONE) {
|
||||
if (mTrustManaged) nextState = STATE_ENTERING;
|
||||
} else if (mState == STATE_ENTERING) {
|
||||
if (!mTrustManaged) nextState = STATE_EXITING;
|
||||
} else if (mState == STATE_VISIBLE) {
|
||||
if (!mTrustManaged) nextState = STATE_EXITING;
|
||||
} else if (mState == STATE_EXITING) {
|
||||
if (mTrustManaged) nextState = STATE_ENTERING;
|
||||
}
|
||||
if (!animate) {
|
||||
if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE;
|
||||
if (nextState == STATE_EXITING) nextState = STATE_GONE;
|
||||
}
|
||||
|
||||
if (nextState != mState) {
|
||||
if (mCurAnimator != null) {
|
||||
mCurAnimator.cancel();
|
||||
mCurAnimator = null;
|
||||
}
|
||||
|
||||
if (nextState == STATE_GONE) {
|
||||
mCurAlpha = 0;
|
||||
mCurInnerRadius = mInnerRadiusEnter;
|
||||
} else if (nextState == STATE_ENTERING) {
|
||||
mCurAnimator = makeEnterAnimator(mCurInnerRadius, mCurAlpha);
|
||||
if (mState == STATE_UNSET) {
|
||||
mCurAnimator.setStartDelay(ENTERING_FROM_UNSET_START_DELAY);
|
||||
}
|
||||
} else if (nextState == STATE_VISIBLE) {
|
||||
mCurAlpha = ALPHA_VISIBLE_MAX;
|
||||
mCurInnerRadius = mInnerRadiusVisibleMax;
|
||||
mCurAnimator = mVisibleAnimator;
|
||||
} else if (nextState == STATE_EXITING) {
|
||||
mCurAnimator = makeExitAnimator(mCurInnerRadius, mCurAlpha);
|
||||
}
|
||||
|
||||
mState = nextState;
|
||||
if (mCurAnimator != null) {
|
||||
mCurAnimator.start();
|
||||
} else {
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Animator makeVisibleAnimator() {
|
||||
return makeAnimators(mInnerRadiusVisibleMax, mInnerRadiusVisibleMin,
|
||||
ALPHA_VISIBLE_MAX, ALPHA_VISIBLE_MIN, VISIBLE_DURATION,
|
||||
mAccelerateDecelerateInterpolator,
|
||||
true /* repeating */, false /* stateUpdateListener */);
|
||||
}
|
||||
|
||||
private Animator makeEnterAnimator(float radius, int alpha) {
|
||||
return makeAnimators(radius, mInnerRadiusVisibleMax,
|
||||
alpha, ALPHA_VISIBLE_MAX, ENTER_DURATION, mLinearOutSlowInInterpolator,
|
||||
false /* repeating */, true /* stateUpdateListener */);
|
||||
}
|
||||
|
||||
private Animator makeExitAnimator(float radius, int alpha) {
|
||||
return makeAnimators(radius, mInnerRadiusExit,
|
||||
alpha, 0, EXIT_DURATION, mFastOutSlowInInterpolator,
|
||||
false /* repeating */, true /* stateUpdateListener */);
|
||||
}
|
||||
|
||||
private Animator makeAnimators(float startRadius, float endRadius,
|
||||
int startAlpha, int endAlpha, long duration, Interpolator interpolator,
|
||||
boolean repeating, boolean stateUpdateListener) {
|
||||
ValueAnimator alphaAnimator = configureAnimator(
|
||||
ValueAnimator.ofInt(startAlpha, endAlpha),
|
||||
duration, mAlphaUpdateListener, interpolator, repeating);
|
||||
ValueAnimator sizeAnimator = configureAnimator(
|
||||
ValueAnimator.ofFloat(startRadius, endRadius),
|
||||
duration, mRadiusUpdateListener, interpolator, repeating);
|
||||
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.playTogether(alphaAnimator, sizeAnimator);
|
||||
if (stateUpdateListener) {
|
||||
set.addListener(new StateUpdateAnimatorListener());
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private ValueAnimator configureAnimator(ValueAnimator animator, long duration,
|
||||
ValueAnimator.AnimatorUpdateListener updateListener, Interpolator interpolator,
|
||||
boolean repeating) {
|
||||
animator.setDuration(duration);
|
||||
animator.addUpdateListener(updateListener);
|
||||
animator.setInterpolator(interpolator);
|
||||
if (repeating) {
|
||||
animator.setRepeatCount(ValueAnimator.INFINITE);
|
||||
animator.setRepeatMode(ValueAnimator.REVERSE);
|
||||
}
|
||||
return animator;
|
||||
}
|
||||
|
||||
private final ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener =
|
||||
new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mCurAlpha = (int) animation.getAnimatedValue();
|
||||
invalidateSelf();
|
||||
}
|
||||
};
|
||||
|
||||
private final ValueAnimator.AnimatorUpdateListener mRadiusUpdateListener =
|
||||
new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mCurInnerRadius = (float) animation.getAnimatedValue();
|
||||
invalidateSelf();
|
||||
}
|
||||
};
|
||||
|
||||
private class StateUpdateAnimatorListener extends AnimatorListenerAdapter {
|
||||
boolean mCancelled;
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mCancelled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mCancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!mCancelled) {
|
||||
updateState(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user