Home | History | Annotate | Download | only in drawable
      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.bitmap.drawable;
     18 
     19 import android.animation.ValueAnimator;
     20 import android.animation.ValueAnimator.AnimatorUpdateListener;
     21 import android.graphics.Canvas;
     22 import android.graphics.ColorFilter;
     23 import android.graphics.Paint;
     24 import android.graphics.Rect;
     25 import android.graphics.drawable.Drawable;
     26 
     27 import com.android.bitmap.drawable.ExtendedBitmapDrawable.ExtendedOptions;
     28 
     29 /**
     30  * A drawable that wraps another drawable and places it in the center of this space. This drawable
     31  * allows a background color for the "tile", and has a fade-out transition when
     32  * {@link #setVisible(boolean, boolean)} indicates that it is no longer visible.
     33  */
     34 public class TileDrawable extends Drawable implements Drawable.Callback {
     35 
     36     private final ExtendedOptions mOpts;
     37     private final Paint mPaint = new Paint();
     38     private final Drawable mInner;
     39     private final int mInnerWidth;
     40     private final int mInnerHeight;
     41 
     42     protected final ValueAnimator mFadeOutAnimator;
     43 
     44     public TileDrawable(Drawable inner, int innerWidth, int innerHeight, int fadeOutDurationMs,
     45             ExtendedOptions opts) {
     46         mOpts = opts;
     47         mInner = inner != null ? inner.mutate() : null;
     48         mInnerWidth = innerWidth;
     49         mInnerHeight = innerHeight;
     50         if (inner != null) {
     51             mInner.setCallback(this);
     52         }
     53 
     54         mFadeOutAnimator = ValueAnimator.ofInt(255, 0)
     55                 .setDuration(fadeOutDurationMs);
     56         mFadeOutAnimator.addUpdateListener(new AnimatorUpdateListener() {
     57             @Override
     58             public void onAnimationUpdate(ValueAnimator animation) {
     59                 setAlpha((Integer) animation.getAnimatedValue());
     60             }
     61         });
     62 
     63         reset();
     64     }
     65 
     66     public void reset() {
     67         setAlpha(0);
     68         setVisible(false);
     69     }
     70 
     71     public Drawable getInnerDrawable() {
     72         return mInner;
     73     }
     74 
     75     @Override
     76     protected void onBoundsChange(Rect bounds) {
     77         super.onBoundsChange(bounds);
     78 
     79         if (mInner == null) {
     80             return;
     81         }
     82 
     83         if (bounds.isEmpty()) {
     84             mInner.setBounds(0, 0, 0, 0);
     85         } else {
     86             final int l = bounds.left + (bounds.width() / 2) - (mInnerWidth / 2);
     87             final int t = bounds.top + (bounds.height() / 2) - (mInnerHeight / 2);
     88             mInner.setBounds(l, t, l + mInnerWidth, t + mInnerHeight);
     89         }
     90     }
     91 
     92     @Override
     93     public void draw(Canvas canvas) {
     94         if (!isVisible() && mPaint.getAlpha() == 0) {
     95             return;
     96         }
     97         final int alpha = mPaint.getAlpha();
     98         mPaint.setColor(mOpts.backgroundColor);
     99         mPaint.setAlpha(alpha);
    100         canvas.drawRect(getBounds(), mPaint);
    101         if (mInner != null) mInner.draw(canvas);
    102     }
    103 
    104     @Override
    105     public void setAlpha(int alpha) {
    106         final int old = mPaint.getAlpha();
    107         mPaint.setAlpha(alpha);
    108         setInnerAlpha(alpha);
    109         if (alpha != old) {
    110             invalidateSelf();
    111         }
    112     }
    113 
    114     @Override
    115     public void setColorFilter(ColorFilter cf) {
    116         mPaint.setColorFilter(cf);
    117         if (mInner != null) mInner.setColorFilter(cf);
    118     }
    119 
    120     @Override
    121     public int getOpacity() {
    122         return 0;
    123     }
    124 
    125     protected int getCurrentAlpha() {
    126         return mPaint.getAlpha();
    127     }
    128 
    129     public boolean setVisible(boolean visible) {
    130         return setVisible(visible, true /* dontcare */);
    131     }
    132 
    133     @Override
    134     public boolean setVisible(boolean visible, boolean restart) {
    135         if (mInner != null) mInner.setVisible(visible, restart);
    136         final boolean changed = super.setVisible(visible, restart);
    137         if (changed) {
    138             if (isVisible()) {
    139                 // pop in (no-op)
    140                 // the transition will still be smooth if the previous state's layer fades out
    141                 mFadeOutAnimator.cancel();
    142                 setAlpha(255);
    143             } else {
    144                 // fade out
    145                 if (mPaint.getAlpha() == 255) {
    146                     mFadeOutAnimator.start();
    147                 }
    148             }
    149         }
    150         return changed;
    151     }
    152 
    153     @Override
    154     protected boolean onLevelChange(int level) {
    155         if (mInner != null)
    156             return mInner.setLevel(level);
    157         else {
    158             return super.onLevelChange(level);
    159         }
    160     }
    161 
    162     /**
    163      * Changes the alpha on just the inner wrapped drawable.
    164      */
    165     public void setInnerAlpha(int alpha) {
    166         if (mInner != null) mInner.setAlpha(alpha);
    167     }
    168 
    169     @Override
    170     public void invalidateDrawable(Drawable who) {
    171         invalidateSelf();
    172     }
    173 
    174     @Override
    175     public void scheduleDrawable(Drawable who, Runnable what, long when) {
    176         scheduleSelf(what, when);
    177     }
    178 
    179     @Override
    180     public void unscheduleDrawable(Drawable who, Runnable what) {
    181         unscheduleSelf(what);
    182     }
    183 }
    184