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;
20d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.TypedArray;
21d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.XmlResourceParser;
22d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.content.res.Resources.NotFoundException;
23d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.util.AttributeSet;
245bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haaseimport android.util.TypedValue;
25d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.util.Xml;
26d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport android.view.animation.AnimationUtils;
27d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport org.xmlpull.v1.XmlPullParser;
28d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport org.xmlpull.v1.XmlPullParserException;
29d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
30d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport java.io.IOException;
31d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haaseimport java.util.ArrayList;
32d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
33d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase/**
346cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * This class is used to instantiate animator XML files into Animator objects.
35d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * <p>
366cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * For performance reasons, inflation relies heavily on pre-processing of
37d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * XML files that is done at build time. Therefore, it is not currently possible
386cfdf4538049e4b96f50d8c0fe3119664420cc34Chet Haase * to use this inflater with an XmlPullParser over a plain XML file at runtime;
39d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * it only works with an XmlPullParser returned from a compiled resource (R.
40d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase * <em>something</em> file.)
41d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase */
42a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haasepublic class AnimatorInflater {
43d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
44d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
45a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * These flags are used when parsing AnimatorSet objects
46d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
47d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int TOGETHER = 0;
48d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int SEQUENTIALLY = 1;
49d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
50d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
51d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * Enum values used in XML attributes to indicate the value for mValueType
52d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
53d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int VALUE_TYPE_FLOAT       = 0;
54d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    private static final int VALUE_TYPE_INT         = 1;
552794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private static final int VALUE_TYPE_COLOR       = 4;
562794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    private static final int VALUE_TYPE_CUSTOM      = 5;
57d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
58d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
59a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * Loads an {@link Animator} object from a resource
60d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     *
61d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param context Application context used to access resources
62d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param id The resource id of the animation to load
63a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase     * @return The animator object reference by the specified id
64d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
65d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
66a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    public static Animator loadAnimator(Context context, int id)
67d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws NotFoundException {
68d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
69d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        XmlResourceParser parser = null;
70d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        try {
71d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            parser = context.getResources().getAnimation(id);
72a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            return createAnimatorFromXml(context, parser);
73d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } catch (XmlPullParserException ex) {
74d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            Resources.NotFoundException rnf =
75d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
76d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    Integer.toHexString(id));
77d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            rnf.initCause(ex);
78d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throw rnf;
79d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } catch (IOException ex) {
80d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            Resources.NotFoundException rnf =
81d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    new Resources.NotFoundException("Can't load animation resource ID #0x" +
82d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    Integer.toHexString(id));
83d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            rnf.initCause(ex);
84d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throw rnf;
85d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        } finally {
86d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            if (parser != null) parser.close();
87d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
88d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
89d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
90a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    private static Animator createAnimatorFromXml(Context c, XmlPullParser parser)
91d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws XmlPullParserException, IOException {
92d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
93a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        return createAnimatorFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
94d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
95d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
96a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    private static Animator createAnimatorFromXml(Context c, XmlPullParser parser,
97a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
98d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws XmlPullParserException, IOException {
99d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
100a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        Animator anim = null;
101a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        ArrayList<Animator> childAnims = null;
102d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
103d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        // Make sure we are on a start tag.
104d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        int type;
105d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        int depth = parser.getDepth();
106d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
107d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
108d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase               && type != XmlPullParser.END_DOCUMENT) {
109d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
110d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            if (type != XmlPullParser.START_TAG) {
111d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                continue;
112d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            }
113d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
114d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            String  name = parser.getName();
115d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
116a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            if (name.equals("objectAnimator")) {
117a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                anim = loadObjectAnimator(c, attrs);
118d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            } else if (name.equals("animator")) {
119d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                anim = loadAnimator(c, attrs, null);
120a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            } else if (name.equals("set")) {
121a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                anim = new AnimatorSet();
122d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                TypedArray a = c.obtainStyledAttributes(attrs,
123a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                        com.android.internal.R.styleable.AnimatorSet);
124a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering,
125d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                        TOGETHER);
126a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim,  ordering);
127d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                a.recycle();
128d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            } else {
129d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                throw new RuntimeException("Unknown animator name: " + parser.getName());
130d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            }
131d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
132d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            if (parent != null) {
133d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                if (childAnims == null) {
134a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                    childAnims = new ArrayList<Animator>();
135d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
136d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                childAnims.add(anim);
137d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            }
138d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
139d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (parent != null && childAnims != null) {
140a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            Animator[] animsArray = new Animator[childAnims.size()];
141d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            int index = 0;
142a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            for (Animator a : childAnims) {
143d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                animsArray[index++] = a;
144d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            }
145d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            if (sequenceOrdering == TOGETHER) {
146d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                parent.playTogether(animsArray);
147d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            } else {
148d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                parent.playSequentially(animsArray);
149d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            }
150d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
151d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
152d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        return anim;
153d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
154d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
155d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
156a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs)
157d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws NotFoundException {
158d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
159a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        ObjectAnimator anim = new ObjectAnimator();
160d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
161d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        loadAnimator(context, attrs, anim);
162d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
163d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        TypedArray a =
164d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PropertyAnimator);
165d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
166d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        String propertyName = a.getString(com.android.internal.R.styleable.PropertyAnimator_propertyName);
167d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
168d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        anim.setPropertyName(propertyName);
169d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
170d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        a.recycle();
171d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
172d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        return anim;
173d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
174d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
175d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    /**
176d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * Creates a new animation whose parameters come from the specified context and
177d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * attributes set.
178d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     *
179d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param context the application environment
180d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     * @param attrs the set of attributes holding the animation parameters
181d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase     */
182a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase    private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, ValueAnimator anim)
183d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            throws NotFoundException {
184d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
185d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        TypedArray a =
186d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator);
187d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
188d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 0);
189d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
190d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
191d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
192d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
193d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                VALUE_TYPE_FLOAT);
194d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
1952794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        if (anim == null) {
1962794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            anim = new ValueAnimator();
1972794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        }
198d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        TypeEvaluator evaluator = null;
1995bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2005bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int valueFromIndex = com.android.internal.R.styleable.Animator_valueFrom;
2015bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int valueToIndex = com.android.internal.R.styleable.Animator_valueTo;
2025bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2035bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean getFloats = (valueType == VALUE_TYPE_FLOAT);
2045bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2055bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        TypedValue tvFrom = a.peekValue(valueFromIndex);
2065bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean hasFrom = (tvFrom != null);
2075bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int fromType = hasFrom ? tvFrom.type : 0;
2085bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        TypedValue tvTo = a.peekValue(valueToIndex);
2095bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        boolean hasTo = (tvTo != null);
2105bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        int toType = hasTo ? tvTo.type : 0;
2115bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2125bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2135bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) ||
2145bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2155bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
2165bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            // special case for colors: ignore valueType and get ints
2175bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            getFloats = false;
21853ee3316bcb3590ff156b3fd7108903c0817c35dChet Haase            anim.setEvaluator(new ArgbEvaluator());
2195bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        }
2205bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase
2215bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        if (getFloats) {
2225bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            float valueFrom;
2235bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            float valueTo;
2245bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            if (hasFrom) {
2255bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (fromType == TypedValue.TYPE_DIMENSION) {
2265bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getDimension(valueFromIndex, 0f);
2275bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2285bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getFloat(valueFromIndex, 0f);
2295bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2305bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2315bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2325bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getDimension(valueToIndex, 0f);
2332794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2345bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getFloat(valueToIndex, 0f);
2352794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2365bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setFloatValues(valueFrom, valueTo);
2375bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2385bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setFloatValues(valueFrom);
2395bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2405bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            } else {
2415bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (toType == TypedValue.TYPE_DIMENSION) {
2425bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueTo = a.getDimension(valueToIndex, 0f);
2432794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                } else {
2445bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueTo = a.getFloat(valueToIndex, 0f);
245d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2465bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                anim.setFloatValues(valueTo);
2472794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            }
2485bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase        } else {
2495bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            int valueFrom;
2505bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            int valueTo;
2515bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            if (hasFrom) {
2525bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (fromType == TypedValue.TYPE_DIMENSION) {
2535bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = (int) a.getDimension(valueFromIndex, 0f);
2545bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2555bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2565bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getColor(valueFromIndex, 0);
2575bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                } else {
2585bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    valueFrom = a.getInt(valueFromIndex, 0);
2595bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                }
2605bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2615bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2625bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = (int) a.getDimension(valueToIndex, 0f);
2635bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2645bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                            (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2655bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getColor(valueToIndex, 0);
2662794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2675bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getInt(valueToIndex, 0);
2682794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2695bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueFrom, valueTo);
2702794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                } else {
2715bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueFrom);
272d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2735bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase            } else {
2745bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                if (hasTo) {
2755bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    if (toType == TypedValue.TYPE_DIMENSION) {
2765bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = (int) a.getDimension(valueToIndex, 0f);
2775bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
2785bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
2795bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getColor(valueToIndex, 0);
2802794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    } else {
2815bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                        valueTo = a.getInt(valueToIndex, 0);
2822794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase                    }
2835bed88e12d0b4e77483e287c068fbf551ecf8a10Chet Haase                    anim.setIntValues(valueTo);
284d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                }
2852794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase            }
286d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
287d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
2882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setDuration(duration);
289d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        anim.setStartDelay(startDelay);
290d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
291d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) {
292d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setRepeatCount(
293d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0));
294d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
295d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) {
296d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setRepeatMode(
297d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                    a.getInt(com.android.internal.R.styleable.Animator_repeatMode,
298a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase                            ValueAnimator.RESTART));
299d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
300d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (evaluator != null) {
301d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setEvaluator(evaluator);
302d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
303d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
304d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        final int resID =
305d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase                a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
306d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        if (resID > 0) {
307d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase            anim.setInterpolator(AnimationUtils.loadInterpolator(context, resID));
308d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        }
309d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        a.recycle();
310d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase
311d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase        return anim;
312d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase    }
313d51d368f2d512ab657b8ae45780c82c0dbea94c3Chet Haase}
314