• 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      * Returns the current animation time in milliseconds. This time should be used when invoking
38      * {@link Animation#setStartTime(long)}. Refer to {@link android.os.SystemClock} for more
39      * information about the different available clocks. The clock used by this method is
40      * <em>not</em> the "wall" clock (it is not {@link System#currentTimeMillis}).
41      *
42      * @return the current animation time in milliseconds
43      *
44      * @see android.os.SystemClock
45      */
currentAnimationTimeMillis()46     public static long currentAnimationTimeMillis() {
47         return SystemClock.uptimeMillis();
48     }
49 
50     /**
51      * Loads an {@link Animation} object from a resource
52      *
53      * @param context Application context used to access resources
54      * @param id The resource id of the animation to load
55      * @return The animation object reference by the specified id
56      * @throws NotFoundException when the animation cannot be loaded
57      */
loadAnimation(Context context, int id)58     public static Animation loadAnimation(Context context, int id)
59             throws NotFoundException {
60 
61         XmlResourceParser parser = null;
62         try {
63             parser = context.getResources().getAnimation(id);
64             return createAnimationFromXml(context, parser);
65         } catch (XmlPullParserException ex) {
66             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
67                     Integer.toHexString(id));
68             rnf.initCause(ex);
69             throw rnf;
70         } catch (IOException ex) {
71             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
72                     Integer.toHexString(id));
73             rnf.initCause(ex);
74             throw rnf;
75         } finally {
76             if (parser != null) parser.close();
77         }
78     }
79 
createAnimationFromXml(Context c, XmlPullParser parser)80     private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
81             throws XmlPullParserException, IOException {
82 
83         return createAnimationFromXml(c, parser, null, Xml.asAttributeSet(parser));
84     }
85 
createAnimationFromXml(Context c, XmlPullParser parser, AnimationSet parent, AttributeSet attrs)86     private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
87             AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
88 
89         Animation anim = null;
90 
91         // Make sure we are on a start tag.
92         int type;
93         int depth = parser.getDepth();
94 
95         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
96                && type != XmlPullParser.END_DOCUMENT) {
97 
98             if (type != XmlPullParser.START_TAG) {
99                 continue;
100             }
101 
102             String  name = parser.getName();
103 
104             if (name.equals("set")) {
105                 anim = new AnimationSet(c, attrs);
106                 createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
107             } else if (name.equals("alpha")) {
108                 anim = new AlphaAnimation(c, attrs);
109             } else if (name.equals("scale")) {
110                 anim = new ScaleAnimation(c, attrs);
111             }  else if (name.equals("rotate")) {
112                 anim = new RotateAnimation(c, attrs);
113             }  else if (name.equals("translate")) {
114                 anim = new TranslateAnimation(c, attrs);
115             } else {
116                 throw new RuntimeException("Unknown animation name: " + parser.getName());
117             }
118 
119             if (parent != null) {
120                 parent.addAnimation(anim);
121             }
122         }
123 
124         return anim;
125 
126     }
127 
loadLayoutAnimation(Context context, int id)128     public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
129             throws NotFoundException {
130 
131         XmlResourceParser parser = null;
132         try {
133             parser = context.getResources().getAnimation(id);
134             return createLayoutAnimationFromXml(context, parser);
135         } catch (XmlPullParserException ex) {
136             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
137                     Integer.toHexString(id));
138             rnf.initCause(ex);
139             throw rnf;
140         } catch (IOException ex) {
141             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
142                     Integer.toHexString(id));
143             rnf.initCause(ex);
144             throw rnf;
145         } finally {
146             if (parser != null) parser.close();
147         }
148     }
149 
createLayoutAnimationFromXml(Context c, XmlPullParser parser)150     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
151             XmlPullParser parser) throws XmlPullParserException, IOException {
152 
153         return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
154     }
155 
createLayoutAnimationFromXml(Context c, XmlPullParser parser, AttributeSet attrs)156     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
157             XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException {
158 
159         LayoutAnimationController controller = null;
160 
161         int type;
162         int depth = parser.getDepth();
163 
164         while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
165                 && type != XmlPullParser.END_DOCUMENT) {
166 
167             if (type != XmlPullParser.START_TAG) {
168                 continue;
169             }
170 
171             String name = parser.getName();
172 
173             if ("layoutAnimation".equals(name)) {
174                 controller = new LayoutAnimationController(c, attrs);
175             } else if ("gridLayoutAnimation".equals(name)) {
176                 controller = new GridLayoutAnimationController(c, attrs);
177             } else {
178                 throw new RuntimeException("Unknown layout animation name: " + name);
179             }
180         }
181 
182         return controller;
183     }
184 
185     /**
186      * Make an animation for objects becoming visible. Uses a slide and fade
187      * effect.
188      *
189      * @param c Context for loading resources
190      * @param fromLeft is the object to be animated coming from the left
191      * @return The new animation
192      */
makeInAnimation(Context c, boolean fromLeft)193     public static Animation makeInAnimation(Context c, boolean fromLeft) {
194         Animation a;
195         if (fromLeft) {
196             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_left);
197         } else {
198             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_right);
199         }
200 
201         a.setInterpolator(new DecelerateInterpolator());
202         a.setStartTime(currentAnimationTimeMillis());
203         return a;
204     }
205 
206     /**
207      * Make an animation for objects becoming invisible. Uses a slide and fade
208      * effect.
209      *
210      * @param c Context for loading resources
211      * @param toRight is the object to be animated exiting to the right
212      * @return The new animation
213      */
makeOutAnimation(Context c, boolean toRight)214     public static Animation makeOutAnimation(Context c, boolean toRight) {
215         Animation a;
216         if (toRight) {
217             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_right);
218         } else {
219             a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_out_left);
220         }
221 
222         a.setInterpolator(new AccelerateInterpolator());
223         a.setStartTime(currentAnimationTimeMillis());
224         return a;
225     }
226 
227 
228     /**
229      * Make an animation for objects becoming visible. Uses a slide up and fade
230      * effect.
231      *
232      * @param c Context for loading resources
233      * @return The new animation
234      */
makeInChildBottomAnimation(Context c)235     public static Animation makeInChildBottomAnimation(Context c) {
236         Animation a;
237         a = AnimationUtils.loadAnimation(c, com.android.internal.R.anim.slide_in_child_bottom);
238         a.setInterpolator(new AccelerateInterpolator());
239         a.setStartTime(currentAnimationTimeMillis());
240         return a;
241     }
242 
243     /**
244      * Loads an {@link Interpolator} object from a resource
245      *
246      * @param context Application context used to access resources
247      * @param id The resource id of the animation to load
248      * @return The animation object reference by the specified id
249      * @throws NotFoundException
250      */
loadInterpolator(Context context, int id)251     public static Interpolator loadInterpolator(Context context, int id) throws NotFoundException {
252         XmlResourceParser parser = null;
253         try {
254             parser = context.getResources().getAnimation(id);
255             return createInterpolatorFromXml(context, parser);
256         } catch (XmlPullParserException ex) {
257             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
258                     Integer.toHexString(id));
259             rnf.initCause(ex);
260             throw rnf;
261         } catch (IOException ex) {
262             NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
263                     Integer.toHexString(id));
264             rnf.initCause(ex);
265             throw rnf;
266         } finally {
267             if (parser != null) parser.close();
268         }
269 
270     }
271 
createInterpolatorFromXml(Context c, XmlPullParser parser)272     private static Interpolator createInterpolatorFromXml(Context c, XmlPullParser parser)
273             throws XmlPullParserException, IOException {
274 
275         Interpolator interpolator = null;
276 
277         // Make sure we are on a start tag.
278         int type;
279         int depth = parser.getDepth();
280 
281         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
282                && type != XmlPullParser.END_DOCUMENT) {
283 
284             if (type != XmlPullParser.START_TAG) {
285                 continue;
286             }
287 
288             AttributeSet attrs = Xml.asAttributeSet(parser);
289 
290             String  name = parser.getName();
291 
292 
293             if (name.equals("linearInterpolator")) {
294                 interpolator = new LinearInterpolator(c, attrs);
295             } else if (name.equals("accelerateInterpolator")) {
296                 interpolator = new AccelerateInterpolator(c, attrs);
297             } else if (name.equals("decelerateInterpolator")) {
298                 interpolator = new DecelerateInterpolator(c, attrs);
299             }  else if (name.equals("accelerateDecelerateInterpolator")) {
300                 interpolator = new AccelerateDecelerateInterpolator(c, attrs);
301             }  else if (name.equals("cycleInterpolator")) {
302                 interpolator = new CycleInterpolator(c, attrs);
303             } else if (name.equals("anticipateInterpolator")) {
304                 interpolator = new AnticipateInterpolator(c, attrs);
305             } else if (name.equals("overshootInterpolator")) {
306                 interpolator = new OvershootInterpolator(c, attrs);
307             } else if (name.equals("anticipateOvershootInterpolator")) {
308                 interpolator = new AnticipateOvershootInterpolator(c, attrs);
309             } else if (name.equals("bounceInterpolator")) {
310                 interpolator = new BounceInterpolator(c, attrs);
311             } else {
312                 throw new RuntimeException("Unknown interpolator name: " + parser.getName());
313             }
314 
315         }
316 
317         return interpolator;
318 
319     }
320 }
321