TileDrawable.java revision df3da61c8f2f54604376d9761649bdba54aa858b
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (C) 2013 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Licensed under the Apache License, Version 2.0 (the "License");
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * you may not use this file except in compliance with the License.
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You may obtain a copy of the License at
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *      http://www.apache.org/licenses/LICENSE-2.0
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Unless required by applicable law or agreed to in writing, software
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * distributed under the License is distributed on an "AS IS" BASIS,
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * See the License for the specific language governing permissions and
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * limitations under the License.
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage com.android.bitmap.drawable;
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.animation.ValueAnimator;
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.animation.ValueAnimator.AnimatorUpdateListener;
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.graphics.Canvas;
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.graphics.ColorFilter;
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.graphics.Paint;
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.graphics.Rect;
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport android.graphics.drawable.Drawable;
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport com.android.bitmap.drawable.ExtendedBitmapDrawable.ExtendedOptions;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A drawable that wraps another drawable and places it in the center of this space. This drawable
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * allows a background color for the "tile", and has a fade-out transition when
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link #setVisible(boolean, boolean)} indicates that it is no longer visible.
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class TileDrawable extends Drawable implements Drawable.Callback {
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final ExtendedOptions mOpts;
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Paint mPaint = new Paint();
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final Drawable mInner;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final int mInnerWidth;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final int mInnerHeight;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected final ValueAnimator mFadeOutAnimator;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public TileDrawable(Drawable inner, int innerWidth, int innerHeight, int fadeOutDurationMs,
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ExtendedOptions opts) {
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mOpts = opts;
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mInner = inner != null ? inner.mutate() : null;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mInnerWidth = innerWidth;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mInnerHeight = innerHeight;
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (inner != null) {
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mInner.setCallback(this);
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mFadeOutAnimator = ValueAnimator.ofInt(255, 0)
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                .setDuration(fadeOutDurationMs);
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mFadeOutAnimator.addUpdateListener(new AnimatorUpdateListener() {
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            @Override
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            public void onAnimationUpdate(ValueAnimator animation) {
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                setAlpha((Integer) animation.getAnimatedValue());
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        });
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        reset();
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void reset() {
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setAlpha(0);
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setVisible(false);
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected void onBoundsChange(Rect bounds) {
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        super.onBoundsChange(bounds);
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner == null) {
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bounds.isEmpty()) {
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mInner.setBounds(0, 0, 0, 0);
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            final int l = bounds.left + (bounds.width() / 2) - (mInnerWidth / 2);
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            final int t = bounds.top + (bounds.height() / 2) - (mInnerHeight / 2);
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            mInner.setBounds(l, t, l + mInnerWidth, t + mInnerHeight);
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void draw(Canvas canvas) {
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!isVisible() && mPaint.getAlpha() == 0) {
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return;
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final int alpha = mPaint.getAlpha();
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mPaint.setColor(mOpts.backgroundColor);
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mPaint.setAlpha(alpha);
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        canvas.drawRect(getBounds(), mPaint);
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner != null) mInner.draw(canvas);
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setAlpha(int alpha) {
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final int old = mPaint.getAlpha();
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mPaint.setAlpha(alpha);
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setInnerAlpha(alpha);
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (alpha != old) {
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            invalidateSelf();
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setColorFilter(ColorFilter cf) {
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        mPaint.setColorFilter(cf);
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner != null) mInner.setColorFilter(cf);
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getOpacity() {
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 0;
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected int getCurrentAlpha() {
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return mPaint.getAlpha();
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean setVisible(boolean visible) {
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return setVisible(visible, true /* dontcare */);
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean setVisible(boolean visible, boolean restart) {
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner != null) mInner.setVisible(visible, restart);
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        final boolean changed = super.setVisible(visible, restart);
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (changed) {
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isVisible()) {
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // pop in (no-op)
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // the transition will still be smooth if the previous state's layer fades out
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                mFadeOutAnimator.cancel();
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                setAlpha(255);
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // fade out
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (mPaint.getAlpha() == 255 && !getBounds().isEmpty()) {
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    mFadeOutAnimator.start();
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return changed;
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean onLevelChange(int level) {
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner != null)
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return mInner.setLevel(level);
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else {
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return super.onLevelChange(level);
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Changes the alpha on just the inner wrapped drawable.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setInnerAlpha(int alpha) {
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (mInner != null) mInner.setAlpha(alpha);
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void invalidateDrawable(Drawable who) {
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        invalidateSelf();
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void scheduleDrawable(Drawable who, Runnable what, long when) {
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        scheduleSelf(what, when);
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    @Override
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void unscheduleDrawable(Drawable who, Runnable what) {
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        unscheduleSelf(what);
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski