Home | History | Annotate | Download | only in animation
      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      */
     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      */
     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 
     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 
     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 
    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 
    150     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
    151             XmlPullParser parser) throws XmlPullParserException, IOException {
    152 
    153         return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
    154     }
    155 
    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      */
    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      */
    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      */
    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      */
    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 
    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