ScrimController.java revision ecc798e6668046c2f67cf30c6ab1db2eba80cab1
1ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi/* 2ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * Copyright (C) 2014 The Android Open Source Project 3ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * 4ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 5ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * you may not use this file except in compliance with the License. 6ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * You may obtain a copy of the License at 7ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * 8ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 9ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * 10ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 11ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 12ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * See the License for the specific language governing permissions and 14ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * limitations under the License 15ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi */ 16ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 17ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggipackage com.android.systemui.statusbar.phone; 18ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 19ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.animation.Animator; 20ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.animation.AnimatorListenerAdapter; 21ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.animation.ValueAnimator; 22ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.content.res.Resources; 23ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.graphics.Color; 24ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.graphics.drawable.ColorDrawable; 25ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.View; 26ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.ViewTreeObserver; 27ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.animation.AccelerateInterpolator; 28ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.animation.AnimationUtils; 29ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.animation.DecelerateInterpolator; 30ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.animation.Interpolator; 31ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggiimport android.view.animation.LinearInterpolator; 32ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 33ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi/** 34ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * Controls both the scrim behind the notifications and in front of the notifications (when a 35ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi * security method gets shown). 36ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi */ 37ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggipublic class ScrimController implements ViewTreeObserver.OnPreDrawListener { 38ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 39ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private static final float SCRIM_BEHIND_ALPHA = 0.62f; 40ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f; 41ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private static final float SCRIM_IN_FRONT_ALPHA = 0.75f; 42ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private static final long ANIMATION_DURATION = 220; 43ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 44ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private final View mScrimBehind; 45ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private final View mScrimInFront; 46ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private final UnlockMethodCache mUnlockMethodCache; 47ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 48ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private boolean mKeyguardShowing; 49ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private float mFraction; 50ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 51ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private boolean mDarkenWhileDragging; 52ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private boolean mBouncerShowing; 53ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private boolean mAnimateChange; 54ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private boolean mUpdatePending; 55ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 56ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private final Interpolator mInterpolator = new DecelerateInterpolator(); 57ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 58ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public ScrimController(View scrimBehind, View scrimInFront) { 59ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimBehind = scrimBehind; 60ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimInFront = scrimInFront; 61ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext()); 62ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 63ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 64ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public void setKeyguardShowing(boolean showing) { 65ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mKeyguardShowing = showing; 66ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi scheduleUpdate(); 67ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 68ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 69ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public void onTrackingStarted() { 70ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure(); 71ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 72ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 73ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public void setPanelExpansion(float fraction) { 74ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mFraction = fraction; 75ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi scheduleUpdate(); 76ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 77ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 78ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public void setBouncerShowing(boolean showing) { 79ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mBouncerShowing = showing; 80ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mAnimateChange = true; 81ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi scheduleUpdate(); 82ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 83ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 84ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void scheduleUpdate() { 85ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (mUpdatePending) return; 86ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this); 87ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mUpdatePending = true; 88ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 89ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 90ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void updateScrims() { 91ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (!mKeyguardShowing) { 92ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi updateScrimNormal(); 93ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimInFrontColor(0); 94ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 95ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi updateScrimKeyguard(); 96ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 97ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mAnimateChange = false; 98ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 99ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 100ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void updateScrimKeyguard() { 101ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (mBouncerShowing) { 102ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA); 103ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimBehindColor(0f); 104ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else if (mDarkenWhileDragging) { 105ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi float behindFraction = Math.max(0, Math.min(mFraction, 1)); 106ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi float fraction = 1 - behindFraction; 107ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA); 108ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD); 109ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 110ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimInFrontColor(0f); 111ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD); 112ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 113ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 114ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 115ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void updateScrimNormal() { 116ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi float frac = mFraction; 117ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi // let's start this 20% of the way down the screen 118ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi frac = frac * 1.2f - 0.2f; 119ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (frac <= 0) { 120ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimBehindColor(0); 121ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 122ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi // woo, special effects 123ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f)))); 124ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimBehindColor(k * SCRIM_BEHIND_ALPHA); 125ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 126ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 127ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 128ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void setScrimBehindColor(float alpha) { 129ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimColor(mScrimBehind, alpha); 130ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 131ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 132ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void setScrimInFrontColor(float alpha) { 133ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi setScrimColor(mScrimInFront, alpha); 134ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (alpha == 0f) { 135ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimInFront.setClickable(false); 136ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 137ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 138ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi // Eat touch events. 139ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimInFront.setClickable(true); 140ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 141ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 142ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 143ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void setScrimColor(View scrim, float alpha) { 144ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi int color = Color.argb((int) (alpha * 255), 0, 0, 0); 145ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (mAnimateChange) { 146ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi startScrimAnimation(scrim, color); 147ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 148ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi scrim.setBackgroundColor(color); 149ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 150ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 151ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 152ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private void startScrimAnimation(final View scrim, int targetColor) { 153ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi int current = getBackgroundAlpha(scrim); 154ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi int target = Color.alpha(targetColor); 155ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (current == targetColor) { 156ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi return; 157ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 158ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi ValueAnimator anim = ValueAnimator.ofInt(current, target); 159ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 160ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi @Override 161ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public void onAnimationUpdate(ValueAnimator animation) { 162ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi int value = (int) animation.getAnimatedValue(); 163ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi scrim.setBackgroundColor(Color.argb(value, 0, 0, 0)); 164ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 165ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi }); 166ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi anim.setInterpolator(mInterpolator); 167ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi anim.setDuration(ANIMATION_DURATION); 168ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi anim.start(); 169ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 170ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 171ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi private int getBackgroundAlpha(View scrim) { 172ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi if (scrim.getBackground() instanceof ColorDrawable) { 173ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi ColorDrawable drawable = (ColorDrawable) scrim.getBackground(); 174ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi return Color.alpha(drawable.getColor()); 175ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } else { 176ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi return 0; 177ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 178ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 179ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi 180ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi @Override 181ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi public boolean onPreDraw() { 182ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this); 183ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi mUpdatePending = false; 184ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi updateScrims(); 185ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi return true; 186ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi } 187ecc798e6668046c2f67cf30c6ab1db2eba80cab1Jorim Jaggi} 188