/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

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.graphics.drawable;
  17. import android.content.res.Resources;
  18. import android.graphics.Canvas;
  19. import android.os.SystemClock;
  20. /**
  21. * An extension of LayerDrawables that is intended to cross-fade between
  22. * the first and second layer. To start the transition, call {@link #startTransition(int)}. To
  23. * display just the first layer, call {@link #resetTransition()}.
  24. * <p>
  25. * It can be defined in an XML file with the <code>&lt;transition></code> element.
  26. * Each Drawable in the transition is defined in a nested <code>&lt;item></code>. For more
  27. * information, see the guide to <a
  28. * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
  29. *
  30. * @attr ref android.R.styleable#LayerDrawableItem_left
  31. * @attr ref android.R.styleable#LayerDrawableItem_top
  32. * @attr ref android.R.styleable#LayerDrawableItem_right
  33. * @attr ref android.R.styleable#LayerDrawableItem_bottom
  34. * @attr ref android.R.styleable#LayerDrawableItem_drawable
  35. * @attr ref android.R.styleable#LayerDrawableItem_id
  36. *
  37. */
  38. public class TransitionDrawable extends LayerDrawable implements Drawable.Callback {
  39. /**
  40. * A transition is about to start.
  41. */
  42. private static final int TRANSITION_STARTING = 0;
  43. /**
  44. * The transition has started and the animation is in progress
  45. */
  46. private static final int TRANSITION_RUNNING = 1;
  47. /**
  48. * No transition will be applied
  49. */
  50. private static final int TRANSITION_NONE = 2;
  51. /**
  52. * The current state of the transition. One of {@link #TRANSITION_STARTING},
  53. * {@link #TRANSITION_RUNNING} and {@link #TRANSITION_NONE}
  54. */
  55. private int mTransitionState = TRANSITION_NONE;
  56. private boolean mReverse;
  57. private long mStartTimeMillis;
  58. private int mFrom;
  59. private int mTo;
  60. private int mDuration;
  61. private int mOriginalDuration;
  62. private int mAlpha = 0;
  63. private boolean mCrossFade;
  64. /**
  65. * Create a new transition drawable with the specified list of layers. At least
  66. * 2 layers are required for this drawable to work properly.
  67. */
  68. public TransitionDrawable(Drawable[] layers) {
  69. this(new TransitionState(null, null, null), layers);
  70. }
  71. /**
  72. * Create a new transition drawable with no layer. To work correctly, at least 2
  73. * layers must be added to this drawable.
  74. *
  75. * @see #TransitionDrawable(Drawable[])
  76. */
  77. TransitionDrawable() {
  78. this(new TransitionState(null, null, null), (Resources)null);
  79. }
  80. private TransitionDrawable(TransitionState state, Resources res) {
  81. super(state, res);
  82. }
  83. private TransitionDrawable(TransitionState state, Drawable[] layers) {
  84. super(layers, state);
  85. }
  86. @Override
  87. LayerState createConstantState(LayerState state, Resources res) {
  88. return new TransitionState((TransitionState) state, this, res);
  89. }
  90. /**
  91. * Begin the second layer on top of the first layer.
  92. *
  93. * @param durationMillis The length of the transition in milliseconds
  94. */
  95. public void startTransition(int durationMillis) {
  96. mFrom = 0;
  97. mTo = 255;
  98. mAlpha = 0;
  99. mDuration = mOriginalDuration = durationMillis;
  100. mReverse = false;
  101. mTransitionState = TRANSITION_STARTING;
  102. invalidateSelf();
  103. }
  104. /**
  105. * Show only the first layer.
  106. */
  107. public void resetTransition() {
  108. mAlpha = 0;
  109. mTransitionState = TRANSITION_NONE;
  110. invalidateSelf();
  111. }
  112. /**
  113. * Reverses the transition, picking up where the transition currently is.
  114. * If the transition is not currently running, this will start the transition
  115. * with the specified duration. If the transition is already running, the last
  116. * known duration will be used.
  117. *
  118. * @param duration The duration to use if no transition is running.
  119. */
  120. public void reverseTransition(int duration) {
  121. final long time = SystemClock.uptimeMillis();
  122. // Animation is over
  123. if (time - mStartTimeMillis > mDuration) {
  124. if (mAlpha == 0) {
  125. mFrom = 0;
  126. mTo = 255;
  127. mAlpha = 0;
  128. mReverse = false;
  129. } else {
  130. mFrom = 255;
  131. mTo = 0;
  132. mAlpha = 255;
  133. mReverse = true;
  134. }
  135. mDuration = mOriginalDuration = duration;
  136. mTransitionState = TRANSITION_STARTING;
  137. invalidateSelf();
  138. return;
  139. }
  140. mReverse = !mReverse;
  141. mFrom = mAlpha;
  142. mTo = mReverse ? 0 : 255;
  143. mDuration = (int) (mReverse ? time - mStartTimeMillis :
  144. mOriginalDuration - (time - mStartTimeMillis));
  145. mTransitionState = TRANSITION_STARTING;
  146. }
  147. @Override
  148. public void draw(Canvas canvas) {
  149. boolean done = true;
  150. switch (mTransitionState) {
  151. case TRANSITION_STARTING:
  152. mStartTimeMillis = SystemClock.uptimeMillis();
  153. done = false;
  154. mTransitionState = TRANSITION_RUNNING;
  155. break;
  156. case TRANSITION_RUNNING:
  157. if (mStartTimeMillis >= 0) {
  158. float normalized = (float)
  159. (SystemClock.uptimeMillis() - mStartTimeMillis) / mDuration;
  160. done = normalized >= 1.0f;
  161. normalized = Math.min(normalized, 1.0f);
  162. mAlpha = (int) (mFrom + (mTo - mFrom) * normalized);
  163. }
  164. break;
  165. }
  166. final int alpha = mAlpha;
  167. final boolean crossFade = mCrossFade;
  168. final ChildDrawable[] array = mLayerState.mChildren;
  169. Drawable d;
  170. d = array[0].mDrawable;
  171. if (crossFade) {
  172. d.setAlpha(255 - alpha);
  173. }
  174. d.draw(canvas);
  175. if (crossFade) {
  176. d.setAlpha(0xFF);
  177. }
  178. if (alpha > 0) {
  179. d = array[1].mDrawable;
  180. d.setAlpha(alpha);
  181. d.draw(canvas);
  182. d.setAlpha(0xFF);
  183. }
  184. if (!done) {
  185. invalidateSelf();
  186. }
  187. }
  188. /**
  189. * Enables or disables the cross fade of the drawables. When cross fade
  190. * is disabled, the first drawable is always drawn opaque. With cross
  191. * fade enabled, the first drawable is drawn with the opposite alpha of
  192. * the second drawable. Cross fade is disabled by default.
  193. *
  194. * @param enabled True to enable cross fading, false otherwise.
  195. */
  196. public void setCrossFadeEnabled(boolean enabled) {
  197. mCrossFade = enabled;
  198. }
  199. /**
  200. * Indicates whether the cross fade is enabled for this transition.
  201. *
  202. * @return True if cross fading is enabled, false otherwise.
  203. */
  204. public boolean isCrossFadeEnabled() {
  205. return mCrossFade;
  206. }
  207. static class TransitionState extends LayerState {
  208. TransitionState(TransitionState orig, TransitionDrawable owner,
  209. Resources res) {
  210. super(orig, owner, res);
  211. }
  212. @Override
  213. public Drawable newDrawable() {
  214. return new TransitionDrawable(this, (Resources)null);
  215. }
  216. @Override
  217. public Drawable newDrawable(Resources res) {
  218. return new TransitionDrawable(this, res);
  219. }
  220. @Override
  221. public int getChangingConfigurations() {
  222. return mChangingConfigurations;
  223. }
  224. }
  225. }