1faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/* 2faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Copyright (C) 2013 The Android Open Source Project 3faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 4faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * you may not use this file except in compliance with the License. 6faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * You may obtain a copy of the License at 7faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 8faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * http://www.apache.org/licenses/LICENSE-2.0 9faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 10faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Unless required by applicable law or agreed to in writing, software 11faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * See the License for the specific language governing permissions and 14faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * limitations under the License. 15faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 166ebe3de331efd00ba23bc4191d4a82cfa4c39160Chet Haase 17d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haasepackage android.transition; 18faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 19bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbyeimport android.annotation.TransitionRes; 20ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport com.android.internal.R; 21ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 22ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport org.xmlpull.v1.XmlPullParser; 23ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport org.xmlpull.v1.XmlPullParserException; 24ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 25faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.Context; 26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.Resources; 27faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.TypedArray; 28faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.XmlResourceParser; 29ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport android.util.ArrayMap; 30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.AttributeSet; 31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.Xml; 32faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.InflateException; 33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup; 34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.io.IOException; 36ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport java.lang.reflect.Constructor; 37ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mountimport java.lang.reflect.InvocationTargetException; 38faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 39faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/** 40faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * This class inflates scenes and transitions from resource files. 41d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * 42d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Information on XML resource descriptions for transitions can be found for 43d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet}, 44d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, 45d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * and {@link android.R.styleable#TransitionManager}. 46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haasepublic class TransitionInflater { 48ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 49ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount private static final Class<?>[] sConstructorSignature = new Class[] { 50ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount Context.class, AttributeSet.class}; 51ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount private final static ArrayMap<String, Constructor> sConstructors = 52ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount new ArrayMap<String, Constructor>(); 53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 54faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private Context mContext; 55faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private TransitionInflater(Context context) { 57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase mContext = context; 58faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 59faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 60faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 61faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Obtains the TransitionInflater from the given context. 62faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 63faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase public static TransitionInflater from(Context context) { 6458ad12208afcf9fdce735dead8449c4db375344dChet Haase return new TransitionInflater(context); 65faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 66faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 67faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 68faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Loads a {@link Transition} object from a resource 69faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 70faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @param resource The resource id of the transition to load 71faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @return The loaded Transition object 72faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @throws android.content.res.Resources.NotFoundException when the 73faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * transition cannot be loaded 74faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 75bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbye public Transition inflateTransition(@TransitionRes int resource) { 76bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbye //noinspection ResourceType 77faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase XmlResourceParser parser = mContext.getResources().getXml(resource); 78faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase try { 79faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null); 80faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (XmlPullParserException e) { 81faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException(e.getMessage()); 82faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 83faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 84faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (IOException e) { 85faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException( 86faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.getPositionDescription() 87faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase + ": " + e.getMessage()); 88faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 89faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 90faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } finally { 91faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.close(); 92faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 93faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 94faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 95faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 96faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Loads a {@link TransitionManager} object from a resource 97faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 98faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @param resource The resource id of the transition manager to load 99faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @return The loaded TransitionManager object 100faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @throws android.content.res.Resources.NotFoundException when the 101faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * transition manager cannot be loaded 102faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 103bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbye public TransitionManager inflateTransitionManager(@TransitionRes int resource, 104bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbye ViewGroup sceneRoot) { 105bc2dd79af9acc538b131506a1ea54fcc7000b164Tor Norbye //noinspection ResourceType 106faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase XmlResourceParser parser = mContext.getResources().getXml(resource); 107faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase try { 108faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot); 109faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (XmlPullParserException e) { 110faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException(e.getMessage()); 111faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 112faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 113faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (IOException e) { 114faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException( 115faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.getPositionDescription() 116faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase + ": " + e.getMessage()); 117faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 118faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 119faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } finally { 120faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.close(); 121faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 122faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 123faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 124faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 125faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Transition loading 126faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 127faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private Transition createTransitionFromXml(XmlPullParser parser, 128ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount AttributeSet attrs, Transition parent) 129faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throws XmlPullParserException, IOException { 130faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 131faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Transition transition = null; 132faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 133faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 134faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 135faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 136faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 137ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount TransitionSet transitionSet = (parent instanceof TransitionSet) 138ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount ? (TransitionSet) parent : null; 139ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount 140faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 141faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 142faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 143faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 144faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 145faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 146faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 147faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 148faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if ("fade".equals(name)) { 149ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new Fade(mContext, attrs); 150d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } else if ("changeBounds".equals(name)) { 151ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new ChangeBounds(mContext, attrs); 152faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("slide".equals(name)) { 153ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new Slide(mContext, attrs); 154d6107a3170df61d9e776fcd5666acfc9135c6f16George Mount } else if ("explode".equals(name)) { 155ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new Explode(mContext, attrs); 156990205eada00ad3e575761d19607bb03e12f9aa3George Mount } else if ("changeImageTransform".equals(name)) { 157ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new ChangeImageTransform(mContext, attrs); 158608b87d9e57b71a86374a439bf5c3febd1e142f2George Mount } else if ("changeTransform".equals(name)) { 159ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new ChangeTransform(mContext, attrs); 160608b87d9e57b71a86374a439bf5c3febd1e142f2George Mount } else if ("changeClipBounds".equals(name)) { 161ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new ChangeClipBounds(mContext, attrs); 162faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("autoTransition".equals(name)) { 163ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new AutoTransition(mContext, attrs); 164faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("recolor".equals(name)) { 165ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new Recolor(mContext, attrs); 1662dcab18c6c9381122df6e06a93912e53dff69408Paul Soulos } else if ("changeScroll".equals(name)) { 1672dcab18c6c9381122df6e06a93912e53dff69408Paul Soulos transition = new ChangeScroll(mContext, attrs); 168aafc91c05acfb2d5a95f46f27e1deb2dfaa15c32Chet Haase } else if ("transitionSet".equals(name)) { 169ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = new TransitionSet(mContext, attrs); 17044d663849481576fb649aeb6234086406ced75f1George Mount } else if ("transition".equals(name)) { 171ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = (Transition) createCustom(attrs, Transition.class, "transition"); 172faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("targets".equals(name)) { 173ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount getTargetIds(parser, attrs, parent); 174ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ("arcMotion".equals(name)) { 175ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount parent.setPathMotion(new ArcMotion(mContext, attrs)); 176ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ("pathMotion".equals(name)) { 177ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount parent.setPathMotion((PathMotion)createCustom(attrs, PathMotion.class, "pathMotion")); 178f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount } else if ("patternPathMotion".equals(name)) { 179f9557619a7643c971e64e5b35583476202e77b7bGeorge Mount parent.setPathMotion(new PatternPathMotion(mContext, attrs)); 180faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 181faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 183ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (transition != null) { 184ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (!parser.isEmptyElementTag()) { 185ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount createTransitionFromXml(parser, attrs, transition); 186ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 187ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (transitionSet != null) { 188ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transitionSet.addTransition(transition); 189ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount transition = null; 190ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if (parent != null) { 191ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not add transition to another transition."); 192ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 193ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 194faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 195faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 196faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return transition; 197faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 198faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 199ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount private Object createCustom(AttributeSet attrs, Class expectedType, String tag) { 20044d663849481576fb649aeb6234086406ced75f1George Mount String className = attrs.getAttributeValue(null, "class"); 20144d663849481576fb649aeb6234086406ced75f1George Mount 20244d663849481576fb649aeb6234086406ced75f1George Mount if (className == null) { 203ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException(tag + " tag must have a 'class' attribute"); 20444d663849481576fb649aeb6234086406ced75f1George Mount } 20544d663849481576fb649aeb6234086406ced75f1George Mount 20644d663849481576fb649aeb6234086406ced75f1George Mount try { 207ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount synchronized (sConstructors) { 208ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount Constructor constructor = sConstructors.get(className); 209ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (constructor == null) { 210ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount Class c = mContext.getClassLoader().loadClass(className) 211ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount .asSubclass(expectedType); 212ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (c != null) { 213ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount constructor = c.getConstructor(sConstructorSignature); 214904de2ec9360de2ee54b91aaf9e141d9d8ab1de1Alan Viverette constructor.setAccessible(true); 215ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount sConstructors.put(className, constructor); 216ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 217ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } 218ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount return constructor.newInstance(mContext, attrs); 21944d663849481576fb649aeb6234086406ced75f1George Mount } 22044d663849481576fb649aeb6234086406ced75f1George Mount } catch (InstantiationException e) { 221ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not instantiate " + expectedType + " class " + 222ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount className, e); 22344d663849481576fb649aeb6234086406ced75f1George Mount } catch (ClassNotFoundException e) { 224ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not instantiate " + expectedType + " class " + 225ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount className, e); 226ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } catch (InvocationTargetException e) { 227ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not instantiate " + expectedType + " class " + 228ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount className, e); 229ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } catch (NoSuchMethodException e) { 230ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not instantiate " + expectedType + " class " + 231ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount className, e); 232ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } catch (IllegalAccessException e) { 233ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount throw new InflateException("Could not instantiate " + expectedType + " class " + 234ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount className, e); 23544d663849481576fb649aeb6234086406ced75f1George Mount } 23644d663849481576fb649aeb6234086406ced75f1George Mount } 23744d663849481576fb649aeb6234086406ced75f1George Mount 238d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase private void getTargetIds(XmlPullParser parser, 239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException { 240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 242faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 243faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 244faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 245faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 246faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 247faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 248faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 249faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (name.equals("target")) { 254ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TransitionTarget); 255ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount int id = a.getResourceId(R.styleable.TransitionTarget_targetId, 0); 2560a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount String transitionName; 257ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount if (id != 0) { 258f976c3d42bc2f14333bae5ed26d96c45d207a443George Mount transition.addTarget(id); 259ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ((id = a.getResourceId(R.styleable.TransitionTarget_excludeId, 0)) != 0) { 260a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount transition.excludeTarget(id, true); 261ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ((transitionName = a.getString(R.styleable.TransitionTarget_targetName)) 26230da61d477bcb6cc7718f9516c444359352fe148George Mount != null) { 2630a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount transition.addTarget(transitionName); 264ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ((transitionName = a.getString(R.styleable.TransitionTarget_excludeName)) 26530da61d477bcb6cc7718f9516c444359352fe148George Mount != null) { 2660a2ae002e60f7ea9b6bea282086b5eb0ae3c6e51George Mount transition.excludeTarget(transitionName, true); 267f976c3d42bc2f14333bae5ed26d96c45d207a443George Mount } else { 268ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount String className = a.getString(R.styleable.TransitionTarget_excludeClass); 269a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount try { 270f976c3d42bc2f14333bae5ed26d96c45d207a443George Mount if (className != null) { 271a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount Class clazz = Class.forName(className); 272a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount transition.excludeTarget(clazz, true); 273ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount } else if ((className = 274ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount a.getString(R.styleable.TransitionTarget_targetClass)) != null) { 275a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount Class clazz = Class.forName(className); 276a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount transition.addTarget(clazz); 277f976c3d42bc2f14333bae5ed26d96c45d207a443George Mount } 278a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount } catch (ClassNotFoundException e) { 279a98fb7ab6a17d27395cf2c8e86060af49b861be6George Mount throw new RuntimeException("Could not create " + className, e); 280f976c3d42bc2f14333bae5ed26d96c45d207a443George Mount } 281faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 282faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 283faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 284faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 285faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 286faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 287faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 288faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 289faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // TransitionManager loading 290faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 291faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 292faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private TransitionManager createTransitionManagerFromXml(XmlPullParser parser, 293faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase AttributeSet attrs, ViewGroup sceneRoot) throws XmlPullParserException, IOException { 294faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 295faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 296faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 297faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 298faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TransitionManager transitionManager = null; 299faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 301faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 302faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 304faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 305faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 306faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 307faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 308faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (name.equals("transitionManager")) { 309faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transitionManager = new TransitionManager(); 310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if (name.equals("transition") && (transitionManager != null)) { 311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase loadTransition(attrs, sceneRoot, transitionManager); 312faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 313faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 314faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 315faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 316faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return transitionManager; 317faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 318faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 319faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private void loadTransition(AttributeSet attrs, ViewGroup sceneRoot, 320d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase TransitionManager transitionManager) throws Resources.NotFoundException { 321faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 322ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TransitionManager); 323ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount int transitionId = a.getResourceId(R.styleable.TransitionManager_transition, -1); 324ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount int fromId = a.getResourceId(R.styleable.TransitionManager_fromScene, -1); 325e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount Scene fromScene = (fromId < 0) ? null: Scene.getSceneForLayout(sceneRoot, fromId, mContext); 326ecd857be3946283ebb4306e2c03ae70f5c5bb152George Mount int toId = a.getResourceId(R.styleable.TransitionManager_toScene, -1); 327e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext); 328e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount 329faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (transitionId >= 0) { 330faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Transition transition = inflateTransition(transitionId); 331faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (transition != null) { 33231a217290cf376d0573fc36e21c8940987485019George Mount if (toScene == null) { 33331a217290cf376d0573fc36e21c8940987485019George Mount throw new RuntimeException("No toScene for transition ID " + transitionId); 33431a217290cf376d0573fc36e21c8940987485019George Mount } 335e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount if (fromScene == null) { 33631a217290cf376d0573fc36e21c8940987485019George Mount transitionManager.setTransition(toScene, transition); 337e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount } else { 338e180337ee99b9155fe441ea55451f4d2167b5d9aGeorge Mount transitionManager.setTransition(fromScene, toScene, transition); 339cfbe9be5b3b701d95fb24fa0f7c8d9be43eec776Adam Powell } 340faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 341faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 342faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase a.recycle(); 343faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 344faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase} 345