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