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