blob: 5c5c2268c891c103ce0394d9df7b8a7eb2b7c3dc [file] [log] [blame]
/*
* 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);
}
}