AnimatorInflater.java revision e5e92602a41a4ddc7b42cd1c171a0edfbd09b8da
1d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase/*
2d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * Copyright (C) 2010 The Android Open Source Project
3d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase *
4d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * you may not use this file except in compliance with the License.
6d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * You may obtain a copy of the License at
7d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase *
8d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase *
10d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * Unless required by applicable law or agreed to in writing, software
11d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * See the License for the specific language governing permissions and
14d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * limitations under the License.
15d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase */
16d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haasepackage android.animation;
17d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
18d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.Context;
19d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.Resources;
20e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.Resources.Theme;
21d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.TypedArray;
22d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.XmlResourceParser;
23d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.Resources.NotFoundException;
24d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.util.AttributeSet;
25f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyarimport android.util.StateSet;
265bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haaseimport android.util.TypedValue;
27d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.util.Xml;
28d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.view.animation.AnimationUtils;
29e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
30e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport com.android.internal.R;
31e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
32d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport org.xmlpull.v1.XmlPullParser;
33d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport org.xmlpull.v1.XmlPullParserException;
34d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
35d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport java.io.IOException;
36d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport java.util.ArrayList;
37d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
38d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase/**
396cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * This class is used to instantiate animator XML files into Animator objects.
40d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * <p>
416cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * For performance reasons, inflation relies heavily on pre-processing of
42d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * XML files that is done at build time. Therefore, it is not currently possible
436cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * to use this inflater with an XmlPullParser over a plain XML file at runtime;
44d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * it only works with an XmlPullParser returned from a compiled resource (R.
45d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * <em>something</em> file.)
46d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase */
47a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haasepublic class AnimatorInflater {
48d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
49d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
50a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * These flags are used when parsing AnimatorSet objects
51d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
52d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int TOGETHER = 0;
53d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int SEQUENTIALLY = 1;
54d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
55d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
56d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * Enum values used in XML attributes to indicate the value for mValueType
57d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
58d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int VALUE_TYPE_FLOAT       = 0;
59d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int VALUE_TYPE_INT         = 1;
602794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private static final int VALUE_TYPE_COLOR       = 4;
612794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private static final int VALUE_TYPE_CUSTOM      = 5;
62d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
63d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
64a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * Loads an {@link Animator} object from a resource
65d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     *
66d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param context Application context used to access resources
67d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param id The resource id of the animation to load
68a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * @return The animator object reference by the specified id
69d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
70d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
71a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    public static Animator loadAnimator(Context context, int id)
72d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws NotFoundException {
73e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return loadAnimator(context.getResources(), context.getTheme(), id);
74e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
75e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
76e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    /**
77e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * Loads an {@link Animator} object from a resource
78e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     *
79e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @param resources The resources
80e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @param theme The theme
81e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @param id The resource id of the animation to load
82e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @return The animator object reference by the specified id
83e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
84e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @hide
85e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     */
86e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public static Animator loadAnimator(Resources resources, Theme theme, int id)
87e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws NotFoundException {
88d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
89d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        XmlResourceParser parser = null;
90d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        try {
91e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            parser = resources.getAnimation(id);
92e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return createAnimatorFromXml(resources, theme, parser);
93d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } catch (XmlPullParserException ex) {
94d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            Resources.NotFoundException rnf =
95d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
96d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    Integer.toHexString(id));
97d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            rnf.initCause(ex);
98d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throw rnf;
99d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } catch (IOException ex) {
100d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            Resources.NotFoundException rnf =
101d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
102d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    Integer.toHexString(id));
103d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            rnf.initCause(ex);
104d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throw rnf;
105d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } finally {
106d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            if (parser != null) parser.close();
107d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
108d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
109d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
110f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar    public static StateListAnimator loadStateListAnimator(Context context, int id)
111f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            throws NotFoundException {
112f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        XmlResourceParser parser = null;
113f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        try {
114f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            parser = context.getResources().getAnimation(id);
115f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
116f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        } catch (XmlPullParserException ex) {
117f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            Resources.NotFoundException rnf =
118f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    new Resources.NotFoundException(
119f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            "Can't load state list animator resource ID #0x" +
120f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                    Integer.toHexString(id)
121f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    );
122f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            rnf.initCause(ex);
123f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            throw rnf;
124f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        } catch (IOException ex) {
125f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            Resources.NotFoundException rnf =
126f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    new Resources.NotFoundException(
127f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            "Can't load state list animator resource ID #0x" +
128f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                    Integer.toHexString(id)
129f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    );
130f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            rnf.initCause(ex);
131f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            throw rnf;
132f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        } finally {
133f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            if (parser != null) {
134f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                parser.close();
135f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            }
136f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        }
137f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar    }
138f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
139f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar    private static StateListAnimator createStateListAnimatorFromXml(Context context,
140f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            XmlPullParser parser, AttributeSet attributeSet)
141f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            throws IOException, XmlPullParserException {
142f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        int type;
143f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        StateListAnimator stateListAnimator = new StateListAnimator();
144f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
145f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        while (true) {
146f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            type = parser.next();
147f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            switch (type) {
148f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                case XmlPullParser.END_DOCUMENT:
149f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                case XmlPullParser.END_TAG:
150f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    return stateListAnimator;
151f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
152f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                case XmlPullParser.START_TAG:
153f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    // parse item
154f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    Animator animator = null;
155f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    if ("item".equals(parser.getName())) {
156f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        int attributeCount = parser.getAttributeCount();
157f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        int[] states = new int[attributeCount];
158f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        int stateIndex = 0;
159f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        for (int i = 0; i < attributeCount; i++) {
160f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            int attrName = attributeSet.getAttributeNameResource(i);
161f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            if (attrName == com.android.internal.R.attr.animation) {
162f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                animator = loadAnimator(context,
163f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                        attributeSet.getAttributeResourceValue(i, 0));
164f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            } else {
165f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                states[stateIndex++] =
166f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                        attributeSet.getAttributeBooleanValue(i, false) ?
167f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                                attrName : -attrName;
168f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            }
169f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
170f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        }
171f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        if (animator == null) {
172e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                            animator = createAnimatorFromXml(context.getResources(),
173e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                                    context.getTheme(), parser);
174f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        }
175f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
176f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        if (animator == null) {
177f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                            throw new Resources.NotFoundException(
178f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                    "animation state item must have a valid animation");
179f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        }
180f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                        stateListAnimator
181f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                                .addState(StateSet.trimStateSet(states, stateIndex), animator);
182f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
183f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    }
184f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar                    break;
185f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar            }
186f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar        }
187f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar    }
188f4c5bf30b445874cf353e1b96cab94185a39ce6dYigit Boyar
189d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
190e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static void parseAnimatorFromTypeArray(ValueAnimator anim, TypedArray a) {
191d9e4a5c2e55883d4eab766d4ab6aee408cb260a0Chet Haase        long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 300);
192d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
193d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
194d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
195d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
196d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                VALUE_TYPE_FLOAT);
197d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
1982794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        if (anim == null) {
1992794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            anim = new ValueAnimator();
2002794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        }
201d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        TypeEvaluator evaluator = null;
2025bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2035bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int valueFromIndex = com.android.internal.R.styleable.Animator_valueFrom;
2045bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int valueToIndex = com.android.internal.R.styleable.Animator_valueTo;
2055bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2065bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean getFloats = (valueType == VALUE_TYPE_FLOAT);
2075bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2085bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        TypedValue tvFrom = a.peekValue(valueFromIndex);
2095bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean hasFrom = (tvFrom != null);
2105bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int fromType = hasFrom ? tvFrom.type : 0;
2115bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        TypedValue tvTo = a.peekValue(valueToIndex);
2125bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean hasTo = (tvTo != null);
2135bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int toType = hasTo ? tvTo.type : 0;
2145bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2155bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2165bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) ||
2175bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2185bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
2195bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            // special case for colors: ignore valueType and get ints
2205bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            getFloats = false;
2211ffb280a7d2c70cc16d709c685f5d31fdb86b5e4George Mount            evaluator = ArgbEvaluator.getInstance();
2225bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        }
2235bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2245bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        if (getFloats) {
2255bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            float valueFrom;
2265bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            float valueTo;
2275bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            if (hasFrom) {
2285bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (fromType == TypedValue.TYPE_DIMENSION) {
2295bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getDimension(valueFromIndex, 0f);
2305bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2315bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getFloat(valueFromIndex, 0f);
2325bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2335bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2345bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2355bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getDimension(valueToIndex, 0f);
2362794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2375bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getFloat(valueToIndex, 0f);
2382794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2395bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setFloatValues(valueFrom, valueTo);
2405bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2415bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setFloatValues(valueFrom);
2425bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2435bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            } else {
2445bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (toType == TypedValue.TYPE_DIMENSION) {
2455bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueTo = a.getDimension(valueToIndex, 0f);
2462794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                } else {
2475bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueTo = a.getFloat(valueToIndex, 0f);
248d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2495bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                anim.setFloatValues(valueTo);
2502794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            }
2515bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        } else {
2525bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            int valueFrom;
2535bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            int valueTo;
2545bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            if (hasFrom) {
2555bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (fromType == TypedValue.TYPE_DIMENSION) {
2565bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = (int) a.getDimension(valueFromIndex, 0f);
2575bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2585bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2595bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getColor(valueFromIndex, 0);
2605bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2615bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getInt(valueFromIndex, 0);
2625bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2635bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2645bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2655bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = (int) a.getDimension(valueToIndex, 0f);
2665bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2675bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                            (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2685bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getColor(valueToIndex, 0);
2692794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2705bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getInt(valueToIndex, 0);
2712794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2725bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueFrom, valueTo);
2732794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                } else {
2745bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueFrom);
275d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2765bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            } else {
2775bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2785bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2795bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = (int) a.getDimension(valueToIndex, 0f);
2805bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2815bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2825bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getColor(valueToIndex, 0);
2832794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2845bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getInt(valueToIndex, 0);
2852794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2865bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueTo);
287d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            }
289d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
290d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
2912794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setDuration(duration);
292d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        anim.setStartDelay(startDelay);
293d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
294d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) {
295d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setRepeatCount(
296d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0));
297d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
298d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) {
299d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setRepeatMode(
300d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    a.getInt(com.android.internal.R.styleable.Animator_repeatMode,
301a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                            ValueAnimator.RESTART));
302d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
303d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (evaluator != null) {
304d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setEvaluator(evaluator);
305d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
306e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
307e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
308e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser)
309e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws XmlPullParserException, IOException {
310e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return createAnimatorFromXml(res, theme, parser, Xml.asAttributeSet(parser), null, 0);
311e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
312e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
313e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
314e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
315e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws XmlPullParserException, IOException {
316e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
317e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        Animator anim = null;
318e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        ArrayList<Animator> childAnims = null;
319e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
320e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        // Make sure we are on a start tag.
321e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int type;
322e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int depth = parser.getDepth();
323e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
324e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
325e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                && type != XmlPullParser.END_DOCUMENT) {
326e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
327e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (type != XmlPullParser.START_TAG) {
328e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                continue;
329e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
330e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
331e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            String name = parser.getName();
332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
333e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (name.equals("objectAnimator")) {
334e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                anim = loadObjectAnimator(res, theme, attrs);
335e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            } else if (name.equals("animator")) {
336e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                anim = loadAnimator(res, theme, attrs, null);
337e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            } else if (name.equals("set")) {
338e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                anim = new AnimatorSet();
339e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                TypedArray a;
340e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                if (theme != null) {
341e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    a = theme.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnimatorSet, 0, 0);
342e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                } else {
343e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    a = res.obtainAttributes(attrs, com.android.internal.R.styleable.AnimatorSet);
344e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                }
345e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering,
346e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                        TOGETHER);
347e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering);
348e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                a.recycle();
349e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            } else {
350e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                throw new RuntimeException("Unknown animator name: " + parser.getName());
351e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
352e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
353e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (parent != null) {
354e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                if (childAnims == null) {
355e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    childAnims = new ArrayList<Animator>();
356e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                }
357e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                childAnims.add(anim);
358e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
359e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
360e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        if (parent != null && childAnims != null) {
361e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            Animator[] animsArray = new Animator[childAnims.size()];
362e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            int index = 0;
363e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            for (Animator a : childAnims) {
364e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                animsArray[index++] = a;
365e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
366e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (sequenceOrdering == TOGETHER) {
367e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                parent.playTogether(animsArray);
368e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            } else {
369e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                parent.playSequentially(animsArray);
370e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
371e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
372e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
373e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return anim;
374e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
375e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
376e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
377e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static ObjectAnimator loadObjectAnimator(Resources res, Theme theme, AttributeSet attrs)
378e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws NotFoundException {
379e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        ObjectAnimator anim = new ObjectAnimator();
380e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
381e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        loadAnimator(res, theme, attrs, anim);
382e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
383e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        TypedArray a;
384e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        if (theme != null) {
385e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            a = theme.obtainStyledAttributes(attrs, R.styleable.PropertyAnimator, 0, 0);
386e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        } else {
387e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            a = res.obtainAttributes(attrs, R.styleable.PropertyAnimator);
388e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
389e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
390e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        String propertyName = a.getString(R.styleable.PropertyAnimator_propertyName);
391e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
392e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        anim.setPropertyName(propertyName);
393e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
394e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        a.recycle();
395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
396e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return anim;
397e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
398e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
399e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    /**
400e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * Creates a new animation whose parameters come from the specified context
401e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * and attributes set.
402e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     *
403e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @param res The resources
404e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     * @param attrs The set of attributes holding the animation parameters
405e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui     */
406e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    private static ValueAnimator loadAnimator(Resources res, Theme theme,
407e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            AttributeSet attrs, ValueAnimator anim)
408e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            throws NotFoundException {
409e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
410e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        TypedArray a;
411e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        if (theme != null) {
412e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            a = theme.obtainStyledAttributes(attrs, R.styleable.Animator, 0, 0);
413e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        } else {
414e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            a = res.obtainAttributes(attrs, R.styleable.Animator);
415e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
416e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
417e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        parseAnimatorFromTypeArray(anim, a);
418d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
419d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        final int resID =
420d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
421d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (resID > 0) {
422e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            anim.setInterpolator(AnimationUtils.loadInterpolator(res, theme, resID));
423d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
424d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        a.recycle();
425d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
426d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        return anim;
427d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
428d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase}
429