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     /**
     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      */
     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      */
     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 
     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 
     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      */
    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 
    166     private static LayoutAnimationController createLayoutAnimationFromXml(Context c,
    167             XmlPullParser parser) throws XmlPullParserException, IOException {
    168 
    169         return createLayoutAnimationFromXml(c, parser, Xml.asAttributeSet(parser));
    170     }
    171 
    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      */
    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      */
    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      */
    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      */
    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 
    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