BarTransitions.java revision c0d7058b14c24cd07912f5629c26b39b7b4673d5
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 17package com.android.systemui.statusbar.phone; 18 19import android.app.ActivityManager; 20import android.content.Context; 21import android.content.res.Resources; 22import android.graphics.Canvas; 23import android.graphics.Color; 24import android.graphics.ColorFilter; 25import android.graphics.PixelFormat; 26import android.graphics.Rect; 27import android.graphics.drawable.Drawable; 28import android.os.SystemClock; 29import android.util.Log; 30import android.view.View; 31 32import com.android.systemui.Interpolators; 33import com.android.systemui.R; 34 35public class BarTransitions { 36 private static final boolean DEBUG = false; 37 private static final boolean DEBUG_COLORS = false; 38 39 public static final boolean HIGH_END = ActivityManager.isHighEndGfx(); 40 41 public static final int MODE_OPAQUE = 0; 42 public static final int MODE_SEMI_TRANSPARENT = 1; 43 public static final int MODE_TRANSLUCENT = 2; 44 public static final int MODE_LIGHTS_OUT = 3; 45 public static final int MODE_TRANSPARENT = 4; 46 public static final int MODE_WARNING = 5; 47 public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6; 48 49 public static final int LIGHTS_IN_DURATION = 250; 50 public static final int LIGHTS_OUT_DURATION = 750; 51 public static final int BACKGROUND_DURATION = 200; 52 53 private final String mTag; 54 private final View mView; 55 private final BarBackgroundDrawable mBarBackground; 56 57 private int mMode; 58 59 public BarTransitions(View view, int gradientResourceId) { 60 mTag = "BarTransitions." + view.getClass().getSimpleName(); 61 mView = view; 62 mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId); 63 if (HIGH_END) { 64 mView.setBackground(mBarBackground); 65 } 66 } 67 68 public int getMode() { 69 return mMode; 70 } 71 72 public void transitionTo(int mode, boolean animate) { 73 // low-end devices do not support translucent modes, fallback to opaque 74 if (!HIGH_END && (mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSLUCENT 75 || mode == MODE_TRANSPARENT)) { 76 mode = MODE_OPAQUE; 77 } 78 if (!HIGH_END && (mode == MODE_LIGHTS_OUT_TRANSPARENT)) { 79 mode = MODE_LIGHTS_OUT; 80 } 81 if (mMode == mode) return; 82 int oldMode = mMode; 83 mMode = mode; 84 if (DEBUG) Log.d(mTag, String.format("%s -> %s animate=%s", 85 modeToString(oldMode), modeToString(mode), animate)); 86 onTransition(oldMode, mMode, animate); 87 } 88 89 protected void onTransition(int oldMode, int newMode, boolean animate) { 90 if (HIGH_END) { 91 applyModeBackground(oldMode, newMode, animate); 92 } 93 } 94 95 protected void applyModeBackground(int oldMode, int newMode, boolean animate) { 96 if (DEBUG) Log.d(mTag, String.format("applyModeBackground oldMode=%s newMode=%s animate=%s", 97 modeToString(oldMode), modeToString(newMode), animate)); 98 mBarBackground.applyModeBackground(oldMode, newMode, animate); 99 } 100 101 public static String modeToString(int mode) { 102 if (mode == MODE_OPAQUE) return "MODE_OPAQUE"; 103 if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT"; 104 if (mode == MODE_TRANSLUCENT) return "MODE_TRANSLUCENT"; 105 if (mode == MODE_LIGHTS_OUT) return "MODE_LIGHTS_OUT"; 106 if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT"; 107 if (mode == MODE_WARNING) return "MODE_WARNING"; 108 if (mode == MODE_LIGHTS_OUT_TRANSPARENT) return "MODE_LIGHTS_OUT_TRANSPARENT"; 109 throw new IllegalArgumentException("Unknown mode " + mode); 110 } 111 112 public void finishAnimations() { 113 mBarBackground.finishAnimation(); 114 } 115 116 protected boolean isLightsOut(int mode) { 117 return mode == MODE_LIGHTS_OUT || mode == MODE_LIGHTS_OUT_TRANSPARENT; 118 } 119 120 private static class BarBackgroundDrawable extends Drawable { 121 private final int mOpaque; 122 private final int mSemiTransparent; 123 private final int mTransparent; 124 private final int mWarning; 125 private final Drawable mGradient; 126 127 private int mMode = -1; 128 private boolean mAnimating; 129 private long mStartTime; 130 private long mEndTime; 131 132 private int mGradientAlpha; 133 private int mColor; 134 135 private int mGradientAlphaStart; 136 private int mColorStart; 137 138 public BarBackgroundDrawable(Context context, int gradientResourceId) { 139 final Resources res = context.getResources(); 140 if (DEBUG_COLORS) { 141 mOpaque = 0xff0000ff; 142 mSemiTransparent = 0x7f0000ff; 143 mTransparent = 0x2f0000ff; 144 mWarning = 0xffff0000; 145 } else { 146 mOpaque = context.getColor(R.color.system_bar_background_opaque); 147 mSemiTransparent = context.getColor( 148 com.android.internal.R.color.system_bar_background_semi_transparent); 149 mTransparent = context.getColor(R.color.system_bar_background_transparent); 150 mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color); 151 } 152 mGradient = context.getDrawable(gradientResourceId); 153 } 154 155 @Override 156 public void setAlpha(int alpha) { 157 // noop 158 } 159 160 @Override 161 public void setColorFilter(ColorFilter colorFilter) { 162 // noop 163 } 164 165 @Override 166 protected void onBoundsChange(Rect bounds) { 167 super.onBoundsChange(bounds); 168 mGradient.setBounds(bounds); 169 } 170 171 public void applyModeBackground(int oldMode, int newMode, boolean animate) { 172 if (mMode == newMode) return; 173 mMode = newMode; 174 mAnimating = animate; 175 if (animate) { 176 long now = SystemClock.elapsedRealtime(); 177 mStartTime = now; 178 mEndTime = now + BACKGROUND_DURATION; 179 mGradientAlphaStart = mGradientAlpha; 180 mColorStart = mColor; 181 } 182 invalidateSelf(); 183 } 184 185 @Override 186 public int getOpacity() { 187 return PixelFormat.TRANSLUCENT; 188 } 189 190 public void finishAnimation() { 191 if (mAnimating) { 192 mAnimating = false; 193 invalidateSelf(); 194 } 195 } 196 197 @Override 198 public void draw(Canvas canvas) { 199 int targetGradientAlpha = 0, targetColor = 0; 200 if (mMode == MODE_WARNING) { 201 targetColor = mWarning; 202 } else if (mMode == MODE_TRANSLUCENT) { 203 targetColor = mSemiTransparent; 204 } else if (mMode == MODE_SEMI_TRANSPARENT) { 205 targetColor = mSemiTransparent; 206 } else if (mMode == MODE_TRANSPARENT || mMode == MODE_LIGHTS_OUT_TRANSPARENT) { 207 targetColor = mTransparent; 208 } else { 209 targetColor = mOpaque; 210 } 211 if (!mAnimating) { 212 mColor = targetColor; 213 mGradientAlpha = targetGradientAlpha; 214 } else { 215 final long now = SystemClock.elapsedRealtime(); 216 if (now >= mEndTime) { 217 mAnimating = false; 218 mColor = targetColor; 219 mGradientAlpha = targetGradientAlpha; 220 } else { 221 final float t = (now - mStartTime) / (float)(mEndTime - mStartTime); 222 final float v = Math.max(0, Math.min( 223 Interpolators.LINEAR.getInterpolation(t), 1)); 224 mGradientAlpha = (int)(v * targetGradientAlpha + mGradientAlphaStart * (1 - v)); 225 mColor = Color.argb( 226 (int)(v * Color.alpha(targetColor) + Color.alpha(mColorStart) * (1 - v)), 227 (int)(v * Color.red(targetColor) + Color.red(mColorStart) * (1 - v)), 228 (int)(v * Color.green(targetColor) + Color.green(mColorStart) * (1 - v)), 229 (int)(v * Color.blue(targetColor) + Color.blue(mColorStart) * (1 - v))); 230 } 231 } 232 if (mGradientAlpha > 0) { 233 mGradient.setAlpha(mGradientAlpha); 234 mGradient.draw(canvas); 235 } 236 if (Color.alpha(mColor) > 0) { 237 canvas.drawColor(mColor); 238 } 239 if (mAnimating) { 240 invalidateSelf(); // keep going 241 } 242 } 243 } 244} 245