• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.view.animation;
18 
19 import org.xmlpull.v1.XmlPullParser;
20 import org.xmlpull.v1.XmlPullParserException;
21 
22 import android.content.Context;
23 import android.content.res.XmlResourceParser;
24 import android.content.res.Resources.NotFoundException;
25 import android.util.AttributeSet;
26 import android.util.Xml;
27 import android.os.SystemClock;
28 
29 import java.io.IOException;
30 
31 /**
32  * Defines common utilities for working with animations.
33  *
34  */
35 public class AnimationUtils {
36 
37     /**
38      * These flags are used when parsing AnimatorSet objects
39      */
40     private static final int TOGETHER = 0;
41     private static final int SEQUENTIALLY = 1;
42 
43 
44     /**
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      */
currentAnimationTimeMillis()54     public static long currentAnimationTimeMillis() {
55         return SystemClock.uptimeMillis();
56     }
57 
58     /**
59      * Loads an {@link Animation} object from a resource
60      *
61      * @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      */
loadAnimation(Context context, int id)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) {
74             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
75                     Integer.toHexString(id));
76             rnf.initCause(ex);
77             throw rnf;
78         } catch (IOException ex) {
79             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
80                     Integer.toHexString(id));
81             rnf.initCause(ex);
82             throw rnf;
83         } finally {
84             if (parser != null) parser.close();
85         }
86     }
87 
createAnimationFromXml(Context c, XmlPullParser parser)88     private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
89             throws XmlPullParserException, IOException {
90 
91         return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
92     }
93 
createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)94     private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
95             AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
96 
97         Animation anim = null;
98 
99         // Make sure we are on a start tag.
100         int type;
101         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();
111 
112             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         }
131 
132         return anim;
133 
134     }
135 
136     /**
137      * Loads a {@link LayoutAnimationController} object from a resource
138      *
139      * @param context Application context used to access resources
140      * @param id The resource id of the animation to load
141      * @return The animation object reference by the specified id
142      * @throws NotFoundException when the layout animation controller cannot be loaded
143      */
loadLayoutAnimation(Context context, int id)144     public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
145             throws NotFoundException {
146 
147         XmlResourceParser parser = null;
148         try {
149             parser = context.getResources().getAnimation(id);
150             return createLayoutAnimationFromXml(context, parser);
151         } catch (XmlPullParserException ex) {
152             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
153                     Integer.toHexString(id));
154             rnf.initCause(ex);
155             throw rnf;
156         } catch (IOException ex) {
157             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
158                     Integer.toHexString(id));
159             rnf.initCause(ex);
160             throw rnf;
161         } finally {
162             if (parser != null) parser.close();
163         }
164     }
165 
createLayoutAnimationFromXml(Context c, XmlPullParser parser)166     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
167             XmlPullParser parser) throws XmlPullParserException, IOException {
168 
169         return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
170     }
171 
createLayoutAnimationFromXml(Context c, XmlPullParser parser, AttributeSet attrs)172     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
173             XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
174 
175         LayoutAnimationController controller = null;
176 
177         int type;
178         int depth = parser.getDepth();
179 
180         while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
181                 && type != XmlPullParser.END_DOCUMENT) {
182 
183             if (type != XmlPullParser.START_TAG) {
184                 continue;
185             }
186 
187             String name = parser.getName();
188 
189             if ("layoutAnimation".equals(name)) {
190                 controller = new LayoutAnimationController(c, attrs);
191             } else if ("gridLayoutAnimation".equals(name)) {
192                 controller = new GridLayoutAnimationController(c, attrs);
193             } else {
194                 throw new RuntimeException("Unknown layout animation name: " + name);
195             }
196         }
197 
198         return controller;
199     }
200 
201     /**
202      * Make an animation for objects becoming visible. Uses a slide and fade
203      * effect.
204      *
205      * @param c Context for loading resources
206      * @param fromLeft is the object to be animated coming from the left
207      * @return The new animation
208      */
makeInAnimation(Context c, boolean fromLeft)209     public static Animation makeInAnimation(Context c, boolean fromLeft) {
210         Animation a;
211         if (fromLeft) {
212             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left);
213         } else {
214             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_right);
215         }
216 
217         a.setInterpolator(new DecelerateInterpolator());
218         a.setStartTime(currentAnimationTimeMillis());
219         return a;
220     }
221 
222     /**
223      * Make an animation for objects becoming invisible. Uses a slide and fade
224      * effect.
225      *
226      * @param c Context for loading resources
227      * @param toRight is the object to be animated exiting to the right
228      * @return The new animation
229      */
makeOutAnimation(Context c, boolean toRight)230     public static Animation makeOutAnimation(Context c, boolean toRight) {
231         Animation a;
232         if (toRight) {
233             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right);
234         } else {
235             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_left);
236         }
237 
238         a.setInterpolator(new AccelerateInterpolator());
239         a.setStartTime(currentAnimationTimeMillis());
240         return a;
241     }
242 
243 
244     /**
245      * Make an animation for objects becoming visible. Uses a slide up and fade
246      * effect.
247      *
248      * @param c Context for loading resources
249      * @return The new animation
250      */
makeInChildBottomAnimation(Context c)251     public static Animation makeInChildBottomAnimation(Context c) {
252         Animation a;
253         a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom);
254         a.setInterpolator(new AccelerateInterpolator());
255         a.setStartTime(currentAnimationTimeMillis());
256         return a;
257     }
258 
259     /**
260      * Loads an {@link Interpolator} object from a resource
261      *
262      * @param context Application context used to access resources
263      * @param id The resource id of the animation to load
264      * @return The animation object reference by the specified id
265      * @throws NotFoundException
266      */
loadInterpolator(Context context, int id)267     public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
268         XmlResourceParser parser = null;
269         try {
270             parser = context.getResources().getAnimation(id);
271             return createInterpolatorFromXml(context, parser);
272         } catch (XmlPullParserException ex) {
273             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
274                     Integer.toHexString(id));
275             rnf.initCause(ex);
276             throw rnf;
277         } catch (IOException ex) {
278             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
279                     Integer.toHexString(id));
280             rnf.initCause(ex);
281             throw rnf;
282         } finally {
283             if (parser != null) parser.close();
284         }
285 
286     }
287 
createInterpolatorFromXml(Context c, XmlPullParser parser)288     private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser)
289             throws XmlPullParserException, IOException {
290 
291         Interpolator interpolator = null;
292 
293         // Make sure we are on a start tag.
294         int type;
295         int depth = parser.getDepth();
296 
297         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
298                && type != XmlPullParser.END_DOCUMENT) {
299 
300             if (type != XmlPullParser.START_TAG) {
301                 continue;
302             }
303 
304             AttributeSet attrs = Xml.asAttributeSet(parser);
305 
306             String  name = parser.getName();
307 
308 
309             if (name.equals("linearInterpolator")) {
310                 interpolator = new LinearInterpolator(c, attrs);
311             } else if (name.equals("accelerateInterpolator")) {
312                 interpolator = new AccelerateInterpolator(c, attrs);
313             } else if (name.equals("decelerateInterpolator")) {
314                 interpolator = new DecelerateInterpolator(c, attrs);
315             }  else if (name.equals("accelerateDecelerateInterpolator")) {
316                 interpolator = new AccelerateDecelerateInterpolator(c, attrs);
317             }  else if (name.equals("cycleInterpolator")) {
318                 interpolator = new CycleInterpolator(c, attrs);
319             } else if (name.equals("anticipateInterpolator")) {
320                 interpolator = new AnticipateInterpolator(c, attrs);
321             } else if (name.equals("overshootInterpolator")) {
322                 interpolator = new OvershootInterpolator(c, attrs);
323             } else if (name.equals("anticipateOvershootInterpolator")) {
324                 interpolator = new AnticipateOvershootInterpolator(c, attrs);
325             } else if (name.equals("bounceInterpolator")) {
326                 interpolator = new BounceInterpolator(c, attrs);
327             } else {
328                 throw new RuntimeException("Unknown interpolator name: " + parser.getName());
329             }
330 
331         }
332 
333         return interpolator;
334 
335     }
336 }
337