ScrimController.java revision ecc798e6668046c2f67cf30c6ab1db2eba80cab1
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 56 private final Interpolator mInterpolator = new DecelerateInterpolator(); 57 58 public ScrimController(View scrimBehind, View scrimInFront) { 59 mScrimBehind = scrimBehind; 60 mScrimInFront = scrimInFront; 61 mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext()); 62 } 63 64 public void setKeyguardShowing(boolean showing) { 65 mKeyguardShowing = showing; 66 scheduleUpdate(); 67 } 68 69 public void onTrackingStarted() { 70 mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure(); 71 } 72 73 public void setPanelExpansion(float fraction) { 74 mFraction = fraction; 75 scheduleUpdate(); 76 } 77 78 public void setBouncerShowing(boolean showing) { 79 mBouncerShowing = showing; 80 mAnimateChange = true; 81 scheduleUpdate(); 82 } 83 84 private void scheduleUpdate() { 85 if (mUpdatePending) return; 86 mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this); 87 mUpdatePending = true; 88 } 89 90 private void updateScrims() { 91 if (!mKeyguardShowing) { 92 updateScrimNormal(); 93 setScrimInFrontColor(0); 94 } else { 95 updateScrimKeyguard(); 96 } 97 mAnimateChange = false; 98 } 99 100 private void updateScrimKeyguard() { 101 if (mBouncerShowing) { 102 setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA); 103 setScrimBehindColor(0f); 104 } else if (mDarkenWhileDragging) { 105 float behindFraction = Math.max(0, Math.min(mFraction, 1)); 106 float fraction = 1 - behindFraction; 107 setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA); 108 setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD); 109 } else { 110 setScrimInFrontColor(0f); 111 setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); 112 } 113 } 114 115 private void updateScrimNormal() { 116 float frac = mFraction; 117 // let's start this 20% of the way down the screen 118 frac = frac * 1.2f - 0.2f; 119 if (frac <= 0) { 120 setScrimBehindColor(0); 121 } else { 122 // woo, special effects 123 final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f)))); 124 setScrimBehindColor(k * SCRIM_BEHIND_ALPHA); 125 } 126 } 127 128 private void setScrimBehindColor(float alpha) { 129 setScrimColor(mScrimBehind, alpha); 130 } 131 132 private void setScrimInFrontColor(float alpha) { 133 setScrimColor(mScrimInFront, alpha); 134 if (alpha == 0f) { 135 mScrimInFront.setClickable(false); 136 } else { 137 138 // Eat touch events. 139 mScrimInFront.setClickable(true); 140 } 141 } 142 143 private void setScrimColor(View scrim, float alpha) { 144 int color = Color.argb((int) (alpha * 255), 0, 0, 0); 145 if (mAnimateChange) { 146 startScrimAnimation(scrim, color); 147 } else { 148 scrim.setBackgroundColor(color); 149 } 150 } 151 152 private void startScrimAnimation(final View scrim, int targetColor) { 153 int current = getBackgroundAlpha(scrim); 154 int target = Color.alpha(targetColor); 155 if (current == targetColor) { 156 return; 157 } 158 ValueAnimator anim = ValueAnimator.ofInt(current, target); 159 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 160 @Override 161 public void onAnimationUpdate(ValueAnimator animation) { 162 int value = (int) animation.getAnimatedValue(); 163 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0)); 164 } 165 }); 166 anim.setInterpolator(mInterpolator); 167 anim.setDuration(ANIMATION_DURATION); 168 anim.start(); 169 } 170 171 private int getBackgroundAlpha(View scrim) { 172 if (scrim.getBackground() instanceof ColorDrawable) { 173 ColorDrawable drawable = (ColorDrawable) scrim.getBackground(); 174 return Color.alpha(drawable.getColor()); 175 } else { 176 return 0; 177 } 178 } 179 180 @Override 181 public boolean onPreDraw() { 182 mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this); 183 mUpdatePending = false; 184 updateScrims(); 185 return true; 186 } 187} 188