blob: 32ff64740eae68272ffb0af21e08ae982edbf895 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.view.animation;
18
19import org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
22import android.content.Context;
23import android.content.res.XmlResourceParser;
24import android.content.res.Resources.NotFoundException;
25import android.util.AttributeSet;
26import android.util.Xml;
27import android.os.SystemClock;
28
29import java.io.IOException;
30
31/**
32 * Defines common utilities for working with animations.
33 *
34 */
35public class AnimationUtils {
Chet Haasef54a8d72010-07-22 14:44:59 -070036
37 /**
Chet Haasea18a86b2010-09-07 13:20:00 -070038 * These flags are used when parsing AnimatorSet objects
Chet Haasef54a8d72010-07-22 14:44:59 -070039 */
40 private static final int TOGETHER = 0;
41 private static final int SEQUENTIALLY = 1;
42
43
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 /**
45 * Returns the current animation time in milliseconds. This time should be used when invoking
46 * {@link Animation#setStartTime(long)}. Refer to {@link android.os.SystemClock} for more
47 * information about the different available clocks. The clock used by this method is
48 * <em>not</em> the "wall" clock (it is not {@link System#currentTimeMillis}).
49 *
50 * @return the current animation time in milliseconds
51 *
52 * @see android.os.SystemClock
53 */
54 public static long currentAnimationTimeMillis() {
55 return SystemClock.uptimeMillis();
56 }
57
58 /**
59 * Loads an {@link Animation} object from a resource
Chet Haasef54a8d72010-07-22 14:44:59 -070060 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 * @param context Application context used to access resources
62 * @param id The resource id of the animation to load
63 * @return The animation object reference by the specified id
64 * @throws NotFoundException when the animation cannot be loaded
65 */
66 public static Animation loadAnimation(Context context, int id)
67 throws NotFoundException {
68
69 XmlResourceParser parser = null;
70 try {
71 parser = context.getResources().getAnimation(id);
72 return createAnimationFromXml(context, parser);
73 } catch (XmlPullParserException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -070074 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
75 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 rnf.initCause(ex);
77 throw rnf;
78 } catch (IOException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -070079 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
80 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 rnf.initCause(ex);
82 throw rnf;
83 } finally {
84 if (parser != null) parser.close();
85 }
86 }
87
88 private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
89 throws XmlPullParserException, IOException {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
92 }
Chet Haasef54a8d72010-07-22 14:44:59 -070093
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -070094 private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
95 AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
Chet Haasef54a8d72010-07-22 14:44:59 -070096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 Animation anim = null;
Chet Haasef54a8d72010-07-22 14:44:59 -070098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 // Make sure we are on a start tag.
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700100 int type;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 int depth = parser.getDepth();
102
103 while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
104 && type != XmlPullParser.END_DOCUMENT) {
105
106 if (type != XmlPullParser.START_TAG) {
107 continue;
108 }
109
110 String name = parser.getName();
Chet Haasef54a8d72010-07-22 14:44:59 -0700111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 if (name.equals("set")) {
113 anim = new AnimationSet(c, attrs);
114 createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
115 } else if (name.equals("alpha")) {
116 anim = new AlphaAnimation(c, attrs);
117 } else if (name.equals("scale")) {
118 anim = new ScaleAnimation(c, attrs);
119 } else if (name.equals("rotate")) {
120 anim = new RotateAnimation(c, attrs);
121 } else if (name.equals("translate")) {
122 anim = new TranslateAnimation(c, attrs);
123 } else {
124 throw new RuntimeException("Unknown animation name: " + parser.getName());
125 }
126
127 if (parent != null) {
128 parent.addAnimation(anim);
129 }
130 }
Chet Haasef54a8d72010-07-22 14:44:59 -0700131
132 return anim;
133
134 }
135
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700136 public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
137 throws NotFoundException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
139 XmlResourceParser parser = null;
140 try {
141 parser = context.getResources().getAnimation(id);
142 return createLayoutAnimationFromXml(context, parser);
143 } catch (XmlPullParserException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700144 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
145 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 rnf.initCause(ex);
147 throw rnf;
148 } catch (IOException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700149 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
150 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 rnf.initCause(ex);
152 throw rnf;
153 } finally {
154 if (parser != null) parser.close();
155 }
156 }
157
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700158 private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
159 XmlPullParser parser) throws XmlPullParserException, IOException {
160
161 return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 }
163
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700164 private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
165 XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166
167 LayoutAnimationController controller = null;
168
169 int type;
170 int depth = parser.getDepth();
171
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700172 while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 && type != XmlPullParser.END_DOCUMENT) {
174
175 if (type != XmlPullParser.START_TAG) {
176 continue;
177 }
178
179 String name = parser.getName();
180
181 if ("layoutAnimation".equals(name)) {
182 controller = new LayoutAnimationController(c, attrs);
183 } else if ("gridLayoutAnimation".equals(name)) {
184 controller = new GridLayoutAnimationController(c, attrs);
185 } else {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700186 throw new RuntimeException("Unknown layout animation name: " + name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 }
188 }
189
190 return controller;
191 }
192
193 /**
194 * Make an animation for objects becoming visible. Uses a slide and fade
195 * effect.
196 *
197 * @param c Context for loading resources
198 * @param fromLeft is the object to be animated coming from the left
199 * @return The new animation
200 */
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700201 public static Animation makeInAnimation(Context c, boolean fromLeft) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 Animation a;
203 if (fromLeft) {
204 a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left);
205 } else {
206 a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_right);
207 }
208
209 a.setInterpolator(new DecelerateInterpolator());
210 a.setStartTime(currentAnimationTimeMillis());
211 return a;
212 }
213
214 /**
215 * Make an animation for objects becoming invisible. Uses a slide and fade
216 * effect.
217 *
218 * @param c Context for loading resources
219 * @param toRight is the object to be animated exiting to the right
220 * @return The new animation
221 */
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700222 public static Animation makeOutAnimation(Context c, boolean toRight) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 Animation a;
224 if (toRight) {
225 a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right);
226 } else {
227 a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_left);
228 }
229
230 a.setInterpolator(new AccelerateInterpolator());
231 a.setStartTime(currentAnimationTimeMillis());
232 return a;
233 }
234
235
236 /**
237 * Make an animation for objects becoming visible. Uses a slide up and fade
238 * effect.
239 *
240 * @param c Context for loading resources
241 * @return The new animation
242 */
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700243 public static Animation makeInChildBottomAnimation(Context c) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 Animation a;
245 a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom);
246 a.setInterpolator(new AccelerateInterpolator());
247 a.setStartTime(currentAnimationTimeMillis());
248 return a;
249 }
250
251 /**
252 * Loads an {@link Interpolator} object from a resource
253 *
254 * @param context Application context used to access resources
255 * @param id The resource id of the animation to load
256 * @return The animation object reference by the specified id
257 * @throws NotFoundException
258 */
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700259 public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 XmlResourceParser parser = null;
261 try {
262 parser = context.getResources().getAnimation(id);
263 return createInterpolatorFromXml(context, parser);
264 } catch (XmlPullParserException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700265 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
266 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 rnf.initCause(ex);
268 throw rnf;
269 } catch (IOException ex) {
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700270 NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
271 Integer.toHexString(id));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 rnf.initCause(ex);
273 throw rnf;
274 } finally {
275 if (parser != null) parser.close();
276 }
277
278 }
279
280 private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser)
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700281 throws XmlPullParserException, IOException {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282
283 Interpolator interpolator = null;
284
285 // Make sure we are on a start tag.
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700286 int type;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 int depth = parser.getDepth();
288
289 while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
290 && type != XmlPullParser.END_DOCUMENT) {
291
292 if (type != XmlPullParser.START_TAG) {
293 continue;
294 }
295
296 AttributeSet attrs = Xml.asAttributeSet(parser);
297
298 String name = parser.getName();
299
300
301 if (name.equals("linearInterpolator")) {
302 interpolator = new LinearInterpolator(c, attrs);
303 } else if (name.equals("accelerateInterpolator")) {
304 interpolator = new AccelerateInterpolator(c, attrs);
305 } else if (name.equals("decelerateInterpolator")) {
306 interpolator = new DecelerateInterpolator(c, attrs);
307 } else if (name.equals("accelerateDecelerateInterpolator")) {
308 interpolator = new AccelerateDecelerateInterpolator(c, attrs);
309 } else if (name.equals("cycleInterpolator")) {
310 interpolator = new CycleInterpolator(c, attrs);
Jean-Baptiste Queru8b066282009-03-25 15:05:51 -0700311 } else if (name.equals("anticipateInterpolator")) {
312 interpolator = new AnticipateInterpolator(c, attrs);
313 } else if (name.equals("overshootInterpolator")) {
314 interpolator = new OvershootInterpolator(c, attrs);
315 } else if (name.equals("anticipateOvershootInterpolator")) {
316 interpolator = new AnticipateOvershootInterpolator(c, attrs);
317 } else if (name.equals("bounceInterpolator")) {
318 interpolator = new BounceInterpolator(c, attrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 } else {
320 throw new RuntimeException("Unknown interpolator name: " + parser.getName());
321 }
322
323 }
324
325 return interpolator;
326
327 }
328}