1 /* 2 * Copyright (C) 2013 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.systemui.statusbar.phone; 18 19 import android.animation.ArgbEvaluator; 20 import android.animation.ValueAnimator; 21 import android.animation.ValueAnimator.AnimatorUpdateListener; 22 import android.app.ActivityManager; 23 import android.content.res.Resources; 24 import android.graphics.drawable.ColorDrawable; 25 import android.graphics.drawable.Drawable; 26 import android.graphics.drawable.TransitionDrawable; 27 import android.util.Log; 28 import android.view.View; 29 30 import com.android.systemui.R; 31 32 public class BarTransitions { 33 private static final boolean DEBUG = false; 34 private static final boolean DEBUG_COLORS = false; 35 36 public static final int MODE_OPAQUE = 0; 37 public static final int MODE_SEMI_TRANSPARENT = 1; 38 public static final int MODE_TRANSLUCENT = 2; 39 public static final int MODE_LIGHTS_OUT = 3; 40 41 public static final int LIGHTS_IN_DURATION = 250; 42 public static final int LIGHTS_OUT_DURATION = 750; 43 public static final int BACKGROUND_DURATION = 200; 44 45 private final String mTag; 46 private final View mView; 47 private final boolean mSupportsTransitions = ActivityManager.isHighEndGfx(); 48 49 private final int mOpaque; 50 private final int mSemiTransparent; 51 52 private int mMode; 53 private ValueAnimator mColorDrawableAnimator; 54 private boolean mColorDrawableShowing; 55 56 private final ColorDrawable mColorDrawable; 57 private final TransitionDrawable mTransitionDrawable; 58 private final AnimatorUpdateListener mAnimatorListener = new AnimatorUpdateListener() { 59 @Override 60 public void onAnimationUpdate(ValueAnimator animator) { 61 mColorDrawable.setColor((Integer) animator.getAnimatedValue()); 62 } 63 }; 64 65 public BarTransitions(View view, int gradientResourceId) { 66 mTag = "BarTransitions." + view.getClass().getSimpleName(); 67 mView = view; 68 final Resources res = mView.getContext().getResources(); 69 70 if (DEBUG_COLORS) { 71 mOpaque = 0xff0000ff; 72 mSemiTransparent = 0x7f0000ff; 73 } else { 74 mOpaque = res.getColor(R.color.system_bar_background_opaque); 75 mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent); 76 } 77 78 mColorDrawable = new ColorDrawable(mOpaque); 79 mTransitionDrawable = new TransitionDrawable( 80 new Drawable[] { res.getDrawable(gradientResourceId), mColorDrawable }); 81 mTransitionDrawable.setCrossFadeEnabled(true); 82 mTransitionDrawable.resetTransition(); 83 if (mSupportsTransitions) { 84 mView.setBackground(mTransitionDrawable); 85 } 86 } 87 88 public int getMode() { 89 return mMode; 90 } 91 92 public void transitionTo(int mode, boolean animate) { 93 if (mMode == mode) return; 94 int oldMode = mMode; 95 mMode = mode; 96 if (DEBUG) Log.d(mTag, String.format("%s -> %s animate=%s", 97 modeToString(oldMode), modeToString(mode), animate)); 98 if (mSupportsTransitions) { 99 onTransition(oldMode, mMode, animate); 100 } 101 } 102 103 private Integer getBackgroundColor(int mode) { 104 if (mode == MODE_SEMI_TRANSPARENT) return mSemiTransparent; 105 if (mode == MODE_OPAQUE) return mOpaque; 106 if (mode == MODE_LIGHTS_OUT) return mOpaque; 107 return null; 108 } 109 110 protected void onTransition(int oldMode, int newMode, boolean animate) { 111 applyModeBackground(oldMode, newMode, animate); 112 } 113 114 protected void applyModeBackground(int oldMode, int newMode, boolean animate) { 115 if (DEBUG) Log.d(mTag, String.format("applyModeBackground %s animate=%s", 116 modeToString(newMode), animate)); 117 cancelColorAnimation(); 118 Integer oldColor = getBackgroundColor(oldMode); 119 Integer newColor = getBackgroundColor(newMode); 120 if (newColor != null) { 121 if (animate && oldColor != null && !oldColor.equals(newColor)) { 122 startColorAnimation(oldColor, newColor); 123 } else if (!newColor.equals(mColorDrawable.getColor())) { 124 if (DEBUG) Log.d(mTag, String.format("setColor = %08x", newColor)); 125 mColorDrawable.setColor(newColor); 126 } 127 } 128 if (newColor == null && mColorDrawableShowing) { 129 if (DEBUG) Log.d(mTag, "Hide color layer"); 130 if (animate) { 131 mTransitionDrawable.reverseTransition(BACKGROUND_DURATION); 132 } else { 133 mTransitionDrawable.resetTransition(); 134 } 135 mColorDrawableShowing = false; 136 } else if (newColor != null && !mColorDrawableShowing) { 137 if (DEBUG) Log.d(mTag, "Show color layer"); 138 mTransitionDrawable.startTransition(animate ? BACKGROUND_DURATION : 0); 139 mColorDrawableShowing = true; 140 } 141 } 142 143 private void startColorAnimation(int from, int to) { 144 if (DEBUG) Log.d(mTag, String.format("startColorAnimation %08x -> %08x", from, to)); 145 mColorDrawableAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to); 146 mColorDrawableAnimator.addUpdateListener(mAnimatorListener); 147 mColorDrawableAnimator.start(); 148 } 149 150 private void cancelColorAnimation() { 151 if (mColorDrawableAnimator != null && mColorDrawableAnimator.isStarted()) { 152 mColorDrawableAnimator.cancel(); 153 mColorDrawableAnimator = null; 154 } 155 } 156 157 public static String modeToString(int mode) { 158 if (mode == MODE_OPAQUE) return "MODE_OPAQUE"; 159 if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT"; 160 if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT"; 161 if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT"; 162 throw new IllegalArgumentException("Unknown mode " + mode); 163 } 164 } 165