/graphics/java/android/graphics/drawable/TransitionDrawable.java
https://github.com/richardfickling/android_frameworks_base · Java · 255 lines · 139 code · 30 blank · 86 comment · 10 complexity · 35d25615c8fcc26313efba8d81e504e5 MD5 · raw file
- /*
- * Copyright (C) 2008 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 android.graphics.drawable;
- import android.content.res.Resources;
- import android.graphics.Canvas;
- import android.os.SystemClock;
- /**
- * An extension of LayerDrawables that is intended to cross-fade between
- * the first and second layer. To start the transition, call {@link #startTransition(int)}. To
- * display just the first layer, call {@link #resetTransition()}.
- * <p>
- * It can be defined in an XML file with the <code><transition></code> element.
- * Each Drawable in the transition is defined in a nested <code><item></code>. For more
- * information, see the guide to <a
- * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
- *
- * @attr ref android.R.styleable#LayerDrawableItem_left
- * @attr ref android.R.styleable#LayerDrawableItem_top
- * @attr ref android.R.styleable#LayerDrawableItem_right
- * @attr ref android.R.styleable#LayerDrawableItem_bottom
- * @attr ref android.R.styleable#LayerDrawableItem_drawable
- * @attr ref android.R.styleable#LayerDrawableItem_id
- *
- */
- public class TransitionDrawable extends LayerDrawable implements Drawable.Callback {
- /**
- * A transition is about to start.
- */
- private static final int TRANSITION_STARTING = 0;
-
- /**
- * The transition has started and the animation is in progress
- */
- private static final int TRANSITION_RUNNING = 1;
-
- /**
- * No transition will be applied
- */
- private static final int TRANSITION_NONE = 2;
-
- /**
- * The current state of the transition. One of {@link #TRANSITION_STARTING},
- * {@link #TRANSITION_RUNNING} and {@link #TRANSITION_NONE}
- */
- private int mTransitionState = TRANSITION_NONE;
- private boolean mReverse;
- private long mStartTimeMillis;
- private int mFrom;
- private int mTo;
- private int mDuration;
- private int mOriginalDuration;
- private int mAlpha = 0;
- private boolean mCrossFade;
- /**
- * Create a new transition drawable with the specified list of layers. At least
- * 2 layers are required for this drawable to work properly.
- */
- public TransitionDrawable(Drawable[] layers) {
- this(new TransitionState(null, null, null), layers);
- }
- /**
- * Create a new transition drawable with no layer. To work correctly, at least 2
- * layers must be added to this drawable.
- *
- * @see #TransitionDrawable(Drawable[])
- */
- TransitionDrawable() {
- this(new TransitionState(null, null, null), (Resources)null);
- }
- private TransitionDrawable(TransitionState state, Resources res) {
- super(state, res);
- }
- private TransitionDrawable(TransitionState state, Drawable[] layers) {
- super(layers, state);
- }
- @Override
- LayerState createConstantState(LayerState state, Resources res) {
- return new TransitionState((TransitionState) state, this, res);
- }
-
- /**
- * Begin the second layer on top of the first layer.
- *
- * @param durationMillis The length of the transition in milliseconds
- */
- public void startTransition(int durationMillis) {
- mFrom = 0;
- mTo = 255;
- mAlpha = 0;
- mDuration = mOriginalDuration = durationMillis;
- mReverse = false;
- mTransitionState = TRANSITION_STARTING;
- invalidateSelf();
- }
-
- /**
- * Show only the first layer.
- */
- public void resetTransition() {
- mAlpha = 0;
- mTransitionState = TRANSITION_NONE;
- invalidateSelf();
- }
- /**
- * Reverses the transition, picking up where the transition currently is.
- * If the transition is not currently running, this will start the transition
- * with the specified duration. If the transition is already running, the last
- * known duration will be used.
- *
- * @param duration The duration to use if no transition is running.
- */
- public void reverseTransition(int duration) {
- final long time = SystemClock.uptimeMillis();
- // Animation is over
- if (time - mStartTimeMillis > mDuration) {
- if (mAlpha == 0) {
- mFrom = 0;
- mTo = 255;
- mAlpha = 0;
- mReverse = false;
- } else {
- mFrom = 255;
- mTo = 0;
- mAlpha = 255;
- mReverse = true;
- }
- mDuration = mOriginalDuration = duration;
- mTransitionState = TRANSITION_STARTING;
- invalidateSelf();
- return;
- }
- mReverse = !mReverse;
- mFrom = mAlpha;
- mTo = mReverse ? 0 : 255;
- mDuration = (int) (mReverse ? time - mStartTimeMillis :
- mOriginalDuration - (time - mStartTimeMillis));
- mTransitionState = TRANSITION_STARTING;
- }
- @Override
- public void draw(Canvas canvas) {
- boolean done = true;
- switch (mTransitionState) {
- case TRANSITION_STARTING:
- mStartTimeMillis = SystemClock.uptimeMillis();
- done = false;
- mTransitionState = TRANSITION_RUNNING;
- break;
- case TRANSITION_RUNNING:
- if (mStartTimeMillis >= 0) {
- float normalized = (float)
- (SystemClock.uptimeMillis() - mStartTimeMillis) / mDuration;
- done = normalized >= 1.0f;
- normalized = Math.min(normalized, 1.0f);
- mAlpha = (int) (mFrom + (mTo - mFrom) * normalized);
- }
- break;
- }
-
- final int alpha = mAlpha;
- final boolean crossFade = mCrossFade;
- final ChildDrawable[] array = mLayerState.mChildren;
- Drawable d;
- d = array[0].mDrawable;
- if (crossFade) {
- d.setAlpha(255 - alpha);
- }
- d.draw(canvas);
- if (crossFade) {
- d.setAlpha(0xFF);
- }
- if (alpha > 0) {
- d = array[1].mDrawable;
- d.setAlpha(alpha);
- d.draw(canvas);
- d.setAlpha(0xFF);
- }
-
- if (!done) {
- invalidateSelf();
- }
- }
- /**
- * Enables or disables the cross fade of the drawables. When cross fade
- * is disabled, the first drawable is always drawn opaque. With cross
- * fade enabled, the first drawable is drawn with the opposite alpha of
- * the second drawable. Cross fade is disabled by default.
- *
- * @param enabled True to enable cross fading, false otherwise.
- */
- public void setCrossFadeEnabled(boolean enabled) {
- mCrossFade = enabled;
- }
- /**
- * Indicates whether the cross fade is enabled for this transition.
- *
- * @return True if cross fading is enabled, false otherwise.
- */
- public boolean isCrossFadeEnabled() {
- return mCrossFade;
- }
- static class TransitionState extends LayerState {
- TransitionState(TransitionState orig, TransitionDrawable owner,
- Resources res) {
- super(orig, owner, res);
- }
- @Override
- public Drawable newDrawable() {
- return new TransitionDrawable(this, (Resources)null);
- }
- @Override
- public Drawable newDrawable(Resources res) {
- return new TransitionDrawable(this, res);
- }
- @Override
- public int getChangingConfigurations() {
- return mChangingConfigurations;
- }
- }
- }