ScrimController.java revision 2fbad7b6a724cf0a5b98b66fe639d58f5ab10af3
1/* 2 * Copyright (C) 2014 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 17package com.android.systemui.statusbar.phone; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ValueAnimator; 22import android.content.res.Resources; 23import android.graphics.Color; 24import android.graphics.drawable.ColorDrawable; 25import android.view.View; 26import android.view.ViewTreeObserver; 27import android.view.animation.AccelerateInterpolator; 28import android.view.animation.AnimationUtils; 29import android.view.animation.DecelerateInterpolator; 30import android.view.animation.Interpolator; 31import android.view.animation.LinearInterpolator; 32 33/** 34 * Controls both the scrim behind the notifications and in front of the notifications (when a 35 * security method gets shown). 36 */ 37public class ScrimController implements ViewTreeObserver.OnPreDrawListener { 38 39 private static final float SCRIM_BEHIND_ALPHA = 0.62f; 40 private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f; 41 private static final float SCRIM_IN_FRONT_ALPHA = 0.75f; 42 private static final long ANIMATION_DURATION = 220; 43 44 private final View mScrimBehind; 45 private final View mScrimInFront; 46 private final UnlockMethodCache mUnlockMethodCache; 47 48 private boolean mKeyguardShowing; 49 private float mFraction; 50 51 private boolean mDarkenWhileDragging; 52 private boolean mBouncerShowing; 53 private boolean mAnimateChange; 54 private boolean mUpdatePending; 55 private boolean mExpanding; 56 57 private final Interpolator mInterpolator = new DecelerateInterpolator(); 58 59 public ScrimController(View scrimBehind, View scrimInFront) { 60 mScrimBehind = scrimBehind; 61 mScrimInFront = scrimInFront; 62 mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext()); 63 } 64 65 public void setKeyguardShowing(boolean showing) { 66 mKeyguardShowing = showing; 67 scheduleUpdate(); 68 } 69 70 public void onTrackingStarted() { 71 mExpanding = true; 72 mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure(); 73 } 74 75 public void onExpandingFinished() { 76 mExpanding = false; 77 } 78 79 public void setPanelExpansion(float fraction) { 80 mFraction = fraction; 81 scheduleUpdate(); 82 } 83 84 public void setBouncerShowing(boolean showing) { 85 mBouncerShowing = showing; 86 mAnimateChange = !mExpanding; 87 scheduleUpdate(); 88 } 89 90 private void scheduleUpdate() { 91 if (mUpdatePending) return; 92 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this); 93 mUpdatePending = true; 94 } 95 96 private void updateScrims() { 97 if (!mKeyguardShowing) { 98 updateScrimNormal(); 99 setScrimInFrontColor(0); 100 } else { 101 updateScrimKeyguard(); 102 } 103 mAnimateChange = false; 104 } 105 106 private void updateScrimKeyguard() { 107 if (mExpanding && mDarkenWhileDragging) { 108 float behindFraction = Math.max(0, Math.min(mFraction, 1)); 109 float fraction = 1 - behindFraction; 110 setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA); 111 setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD); 112 } else if (mBouncerShowing) { 113 setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA); 114 setScrimBehindColor(0f); 115 } else { 116 setScrimInFrontColor(0f); 117 setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); 118 } 119 } 120 121 private void updateScrimNormal() { 122 float frac = mFraction; 123 // let's start this 20% of the way down the screen 124 frac = frac * 1.2f - 0.2f; 125 if (frac <= 0) { 126 setScrimBehindColor(0); 127 } else { 128 // woo, special effects 129 final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f)))); 130 setScrimBehindColor(k * SCRIM_BEHIND_ALPHA); 131 } 132 } 133 134 private void setScrimBehindColor(float alpha) { 135 setScrimColor(mScrimBehind, alpha); 136 } 137 138 private void setScrimInFrontColor(float alpha) { 139 setScrimColor(mScrimInFront, alpha); 140 if (alpha == 0f) { 141 mScrimInFront.setClickable(false); 142 } else { 143 144 // Eat touch events. 145 mScrimInFront.setClickable(true); 146 } 147 } 148 149 private void setScrimColor(View scrim, float alpha) { 150 int color = Color.argb((int) (alpha * 255), 0, 0, 0); 151 if (mAnimateChange) { 152 startScrimAnimation(scrim, color); 153 } else { 154 scrim.setBackgroundColor(color); 155 } 156 } 157 158 private void startScrimAnimation(final View scrim, int targetColor) { 159 int current = getBackgroundAlpha(scrim); 160 int target = Color.alpha(targetColor); 161 if (current == targetColor) { 162 return; 163 } 164 ValueAnimator anim = ValueAnimator.ofInt(current, target); 165 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 166 @Override 167 public void onAnimationUpdate(ValueAnimator animation) { 168 int value = (int) animation.getAnimatedValue(); 169 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0)); 170 } 171 }); 172 anim.setInterpolator(mInterpolator); 173 anim.setDuration(ANIMATION_DURATION); 174 anim.start(); 175 } 176 177 private int getBackgroundAlpha(View scrim) { 178 if (scrim.getBackground() instanceof ColorDrawable) { 179 ColorDrawable drawable = (ColorDrawable) scrim.getBackground(); 180 return Color.alpha(drawable.getColor()); 181 } else { 182 return 0; 183 } 184 } 185 186 @Override 187 public boolean onPreDraw() { 188 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this); 189 mUpdatePending = false; 190 updateScrims(); 191 return true; 192 } 193} 194