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