193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/* 293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Copyright (C) 2013 The Android Open Source Project 393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License"); 593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you may not use this file except in compliance with the License. 693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You may obtain a copy of the License at 793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * http://www.apache.org/licenses/LICENSE-2.0 993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * 1093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Unless required by applicable law or agreed to in writing, software 1193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS, 1293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * See the License for the specific language governing permissions and 1493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * limitations under the License. 1593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 1693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpackage com.android.bitmap.drawable; 1893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 1993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.animation.ValueAnimator; 2093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.animation.ValueAnimator.AnimatorUpdateListener; 2193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Canvas; 2293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.ColorFilter; 2393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Paint; 2493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.Rect; 2593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.graphics.drawable.Drawable; 2693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 275030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Weiimport com.android.bitmap.drawable.ExtendedBitmapDrawable.ExtendedOptions; 285030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei 2993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/** 3093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * A drawable that wraps another drawable and places it in the center of this space. This drawable 3193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * allows a background color for the "tile", and has a fade-out transition when 3293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * {@link #setVisible(boolean, boolean)} indicates that it is no longer visible. 3393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 3493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpublic class TileDrawable extends Drawable implements Drawable.Callback { 3593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 365030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei private final ExtendedOptions mOpts; 3793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final Paint mPaint = new Paint(); 3893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final Drawable mInner; 3993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final int mInnerWidth; 4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein private final int mInnerHeight; 4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected final ValueAnimator mFadeOutAnimator; 4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 445030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei public TileDrawable(Drawable inner, int innerWidth, int innerHeight, int fadeOutDurationMs, 455030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei ExtendedOptions opts) { 465030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei mOpts = opts; 475030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei mInner = inner != null ? inner.mutate() : null; 4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInnerWidth = innerWidth; 4993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInnerHeight = innerHeight; 505030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (inner != null) { 515030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei mInner.setCallback(this); 525030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei } 5393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 5493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mFadeOutAnimator = ValueAnimator.ofInt(255, 0) 5593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein .setDuration(fadeOutDurationMs); 5693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mFadeOutAnimator.addUpdateListener(new AnimatorUpdateListener() { 5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 5893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void onAnimationUpdate(ValueAnimator animation) { 5993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setAlpha((Integer) animation.getAnimatedValue()); 6093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 6193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein }); 6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 6393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein reset(); 6493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 6593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 6693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void reset() { 6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setAlpha(0); 6893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setVisible(false); 6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 7093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 7109f46006437e7de33afdb51192bf0bdc08e97040Mark Wei public Drawable getInnerDrawable() { 7209f46006437e7de33afdb51192bf0bdc08e97040Mark Wei return mInner; 7309f46006437e7de33afdb51192bf0bdc08e97040Mark Wei } 7409f46006437e7de33afdb51192bf0bdc08e97040Mark Wei 7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected void onBoundsChange(Rect bounds) { 7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein super.onBoundsChange(bounds); 7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 795030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner == null) { 805030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei return; 815030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei } 825030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei 8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (bounds.isEmpty()) { 8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInner.setBounds(0, 0, 0, 0); 8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int l = bounds.left + (bounds.width() / 2) - (mInnerWidth / 2); 8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int t = bounds.top + (bounds.height() / 2) - (mInnerHeight / 2); 8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mInner.setBounds(l, t, l + mInnerWidth, t + mInnerHeight); 8993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 9093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 9193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 9293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 9393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void draw(Canvas canvas) { 9493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (!isVisible() && mPaint.getAlpha() == 0) { 9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return; 9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 975030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei final int alpha = mPaint.getAlpha(); 98df3da61c8f2f54604376d9761649bdba54aa858bMark Wei mPaint.setColor(mOpts.backgroundColor); 99cd728097ff189542877a2952879a3aa3c6cb5666Mark Wei mPaint.setAlpha(alpha); 100df3da61c8f2f54604376d9761649bdba54aa858bMark Wei canvas.drawRect(getBounds(), mPaint); 1015030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner != null) mInner.draw(canvas); 10293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 10393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setAlpha(int alpha) { 10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final int old = mPaint.getAlpha(); 10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setAlpha(alpha); 10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setInnerAlpha(alpha); 10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (alpha != old) { 11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 11293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 11393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 11493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 11593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setColorFilter(ColorFilter cf) { 11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mPaint.setColorFilter(cf); 1175030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner != null) mInner.setColorFilter(cf); 11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 11993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public int getOpacity() { 12293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return 0; 12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected int getCurrentAlpha() { 12693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return mPaint.getAlpha(); 12793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 12893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 12993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public boolean setVisible(boolean visible) { 13093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return setVisible(visible, true /* dontcare */); 13193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 13293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 13393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 13493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public boolean setVisible(boolean visible, boolean restart) { 1355030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner != null) mInner.setVisible(visible, restart); 13693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein final boolean changed = super.setVisible(visible, restart); 13793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (changed) { 13893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein if (isVisible()) { 13993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // pop in (no-op) 14093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // the transition will still be smooth if the previous state's layer fades out 14193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mFadeOutAnimator.cancel(); 14293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein setAlpha(255); 14393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } else { 14493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein // fade out 145d732a611bd661fc2ac3c801a545cfbba0f179484Mark Wei if (mPaint.getAlpha() == 255) { 14693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein mFadeOutAnimator.start(); 14793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 14893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 14993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 15093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein return changed; 15193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 15293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 15393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 15493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein protected boolean onLevelChange(int level) { 1555030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner != null) 1565030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei return mInner.setLevel(level); 1575030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei else { 1585030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei return super.onLevelChange(level); 1595030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei } 16093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 16293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein /** 16393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Changes the alpha on just the inner wrapped drawable. 16493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */ 16593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void setInnerAlpha(int alpha) { 1665030ae34cd5978a8ab8a06f6c3b69b8645873122Mark Wei if (mInner != null) mInner.setAlpha(alpha); 16793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 16893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 16993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 17093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void invalidateDrawable(Drawable who) { 17193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein invalidateSelf(); 17293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 17393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 17493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 17593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void scheduleDrawable(Drawable who, Runnable what, long when) { 17693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein scheduleSelf(what, when); 17793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 17893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein 17993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein @Override 18093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein public void unscheduleDrawable(Drawable who, Runnable what) { 18193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein unscheduleSelf(what); 18293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein } 18393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein} 184