| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.bitmap.drawable; |
| |
| import android.animation.ValueAnimator; |
| import android.animation.ValueAnimator.AnimatorUpdateListener; |
| import android.graphics.Canvas; |
| import android.graphics.ColorFilter; |
| import android.graphics.Paint; |
| import android.graphics.Rect; |
| import android.graphics.drawable.Drawable; |
| |
| import com.android.bitmap.drawable.ExtendedBitmapDrawable.ExtendedOptions; |
| |
| /** |
| * A drawable that wraps another drawable and places it in the center of this space. This drawable |
| * allows a background color for the "tile", and has a fade-out transition when |
| * {@link #setVisible(boolean, boolean)} indicates that it is no longer visible. |
| */ |
| public class TileDrawable extends Drawable implements Drawable.Callback { |
| |
| private final ExtendedOptions mOpts; |
| private final Paint mPaint = new Paint(); |
| private final Drawable mInner; |
| private final int mInnerWidth; |
| private final int mInnerHeight; |
| |
| protected final ValueAnimator mFadeOutAnimator; |
| |
| public TileDrawable(Drawable inner, int innerWidth, int innerHeight, int fadeOutDurationMs, |
| ExtendedOptions opts) { |
| mOpts = opts; |
| mInner = inner != null ? inner.mutate() : null; |
| mInnerWidth = innerWidth; |
| mInnerHeight = innerHeight; |
| if (inner != null) { |
| mInner.setCallback(this); |
| } |
| |
| mFadeOutAnimator = ValueAnimator.ofInt(255, 0) |
| .setDuration(fadeOutDurationMs); |
| mFadeOutAnimator.addUpdateListener(new AnimatorUpdateListener() { |
| @Override |
| public void onAnimationUpdate(ValueAnimator animation) { |
| setAlpha((Integer) animation.getAnimatedValue()); |
| } |
| }); |
| |
| reset(); |
| } |
| |
| public void reset() { |
| setAlpha(0); |
| setVisible(false); |
| } |
| |
| public Drawable getInnerDrawable() { |
| return mInner; |
| } |
| |
| @Override |
| protected void onBoundsChange(Rect bounds) { |
| super.onBoundsChange(bounds); |
| |
| if (mInner == null) { |
| return; |
| } |
| |
| if (bounds.isEmpty()) { |
| mInner.setBounds(0, 0, 0, 0); |
| } else { |
| final int l = bounds.left + (bounds.width() / 2) - (mInnerWidth / 2); |
| final int t = bounds.top + (bounds.height() / 2) - (mInnerHeight / 2); |
| mInner.setBounds(l, t, l + mInnerWidth, t + mInnerHeight); |
| } |
| } |
| |
| @Override |
| public void draw(Canvas canvas) { |
| if (!isVisible() && mPaint.getAlpha() == 0) { |
| return; |
| } |
| final int alpha = mPaint.getAlpha(); |
| mPaint.setColor(mOpts.backgroundColor); |
| mPaint.setAlpha(alpha); |
| canvas.drawRect(getBounds(), mPaint); |
| if (mInner != null) mInner.draw(canvas); |
| } |
| |
| @Override |
| public void setAlpha(int alpha) { |
| final int old = mPaint.getAlpha(); |
| mPaint.setAlpha(alpha); |
| setInnerAlpha(alpha); |
| if (alpha != old) { |
| invalidateSelf(); |
| } |
| } |
| |
| @Override |
| public void setColorFilter(ColorFilter cf) { |
| mPaint.setColorFilter(cf); |
| if (mInner != null) mInner.setColorFilter(cf); |
| } |
| |
| @Override |
| public int getOpacity() { |
| return 0; |
| } |
| |
| protected int getCurrentAlpha() { |
| return mPaint.getAlpha(); |
| } |
| |
| public boolean setVisible(boolean visible) { |
| return setVisible(visible, true /* dontcare */); |
| } |
| |
| @Override |
| public boolean setVisible(boolean visible, boolean restart) { |
| if (mInner != null) mInner.setVisible(visible, restart); |
| final boolean changed = super.setVisible(visible, restart); |
| if (changed) { |
| if (isVisible()) { |
| // pop in (no-op) |
| // the transition will still be smooth if the previous state's layer fades out |
| mFadeOutAnimator.cancel(); |
| setAlpha(255); |
| } else { |
| // fade out |
| if (mPaint.getAlpha() == 255) { |
| mFadeOutAnimator.start(); |
| } |
| } |
| } |
| return changed; |
| } |
| |
| @Override |
| protected boolean onLevelChange(int level) { |
| if (mInner != null) |
| return mInner.setLevel(level); |
| else { |
| return super.onLevelChange(level); |
| } |
| } |
| |
| /** |
| * Changes the alpha on just the inner wrapped drawable. |
| */ |
| public void setInnerAlpha(int alpha) { |
| if (mInner != null) mInner.setAlpha(alpha); |
| } |
| |
| @Override |
| public void invalidateDrawable(Drawable who) { |
| invalidateSelf(); |
| } |
| |
| @Override |
| public void scheduleDrawable(Drawable who, Runnable what, long when) { |
| scheduleSelf(what, when); |
| } |
| |
| @Override |
| public void unscheduleDrawable(Drawable who, Runnable what) { |
| unscheduleSelf(what); |
| } |
| } |