Home | History | Annotate | Download | only in phone
      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