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 19faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.Context; 20faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.Resources; 21faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.TypedArray; 22faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.content.res.XmlResourceParser; 23faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.AttributeSet; 24faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.util.Xml; 25faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.InflateException; 26faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.ViewGroup; 27faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport android.view.animation.AnimationUtils; 28faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport org.xmlpull.v1.XmlPullParser; 29faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport org.xmlpull.v1.XmlPullParserException; 30faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 31faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.io.IOException; 32faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haaseimport java.util.ArrayList; 33faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 34faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase/** 35faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * This class inflates scenes and transitions from resource files. 36d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * 37d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * Information on XML resource descriptions for transitions can be found for 38d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#Transition}, {@link android.R.styleable#TransitionSet}, 39d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * {@link android.R.styleable#TransitionTarget}, {@link android.R.styleable#Fade}, 40d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase * and {@link android.R.styleable#TransitionManager}. 41faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 42faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haasepublic class TransitionInflater { 43faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 44faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private Context mContext; 45faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 46faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private TransitionInflater(Context context) { 47faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase mContext = context; 48faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 49faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 50faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 51faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Obtains the TransitionInflater from the given context. 52faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 53faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase public static TransitionInflater from(Context context) { 5458ad12208afcf9fdce735dead8449c4db375344dChet Haase return new TransitionInflater(context); 55faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 56faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 57faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 58faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Loads a {@link Transition} object from a resource 59faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 60faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @param resource The resource id of the transition to load 61faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @return The loaded Transition object 62faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @throws android.content.res.Resources.NotFoundException when the 63faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * transition cannot be loaded 64faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 65faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase public Transition inflateTransition(int resource) { 66faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase XmlResourceParser parser = mContext.getResources().getXml(resource); 67faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase try { 68faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null); 69faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (XmlPullParserException e) { 70faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException(e.getMessage()); 71faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 72faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 73faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (IOException e) { 74faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException( 75faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.getPositionDescription() 76faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase + ": " + e.getMessage()); 77faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 78faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 79faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } finally { 80faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.close(); 81faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 82faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 83faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 84faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase /** 85faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * Loads a {@link TransitionManager} object from a resource 86faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 87faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 88faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * 89faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @param resource The resource id of the transition manager to load 90faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @return The loaded TransitionManager object 91faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * @throws android.content.res.Resources.NotFoundException when the 92faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase * transition manager cannot be loaded 93faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase */ 94faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase public TransitionManager inflateTransitionManager(int resource, ViewGroup sceneRoot) { 95faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase XmlResourceParser parser = mContext.getResources().getXml(resource); 96faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase try { 97faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot); 98faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (XmlPullParserException e) { 99faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException(e.getMessage()); 100faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 101faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 102faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } catch (IOException e) { 103faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase InflateException ex = new InflateException( 104faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.getPositionDescription() 105faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase + ": " + e.getMessage()); 106faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ex.initCause(e); 107faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw ex; 108faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } finally { 109faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase parser.close(); 110faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 111faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 112faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 113faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 114faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Transition loading 115faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 116faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 117faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private Transition createTransitionFromXml(XmlPullParser parser, 118d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase AttributeSet attrs, TransitionSet transitionSet) 119faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throws XmlPullParserException, IOException { 120faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 121faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Transition transition = null; 122faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 123faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 124faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 125faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 126faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 127faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 128faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 129faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 130faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase boolean newTransition = false; 131faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 132faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 133faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 134faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 135faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 136faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 137faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if ("fade".equals(name)) { 138d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase TypedArray a = mContext.obtainStyledAttributes(attrs, 139d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase com.android.internal.R.styleable.Fade); 140d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int fadingMode = a.getInt(com.android.internal.R.styleable.Fade_fadingMode, 141d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase Fade.IN | Fade.OUT); 142d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transition = new Fade(fadingMode); 143faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 144d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } else if ("changeBounds".equals(name)) { 145d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transition = new ChangeBounds(); 146faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 147faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("slide".equals(name)) { 148faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transition = new Slide(); 149faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 150faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("autoTransition".equals(name)) { 151faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transition = new AutoTransition(); 152faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 153faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("recolor".equals(name)) { 154faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transition = new Recolor(); 155faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 156aafc91c05acfb2d5a95f46f27e1deb2dfaa15c32Chet Haase } else if ("transitionSet".equals(name)) { 157d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transition = new TransitionSet(); 158d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase TypedArray a = mContext.obtainStyledAttributes(attrs, 159d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase com.android.internal.R.styleable.TransitionSet); 160d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int ordering = a.getInt( 161d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase com.android.internal.R.styleable.TransitionSet_transitionOrdering, 162d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase TransitionSet.ORDERING_TOGETHER); 163d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase ((TransitionSet) transition).setOrdering(ordering); 164d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase createTransitionFromXml(parser, attrs, ((TransitionSet) transition)); 165d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase a.recycle(); 166faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase newTransition = true; 167faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if ("targets".equals(name)) { 168faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (parser.getDepth() - 1 > depth && transition != null) { 169faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // We're inside the child tag - add targets to the child 170d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase getTargetIds(parser, attrs, transition); 171d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase } else if (parser.getDepth() - 1 == depth && transitionSet != null) { 172d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase // add targets to the set 173d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase getTargetIds(parser, attrs, transitionSet); 174faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 175faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 176faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (transition != null || "targets".equals(name)) { 177faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (newTransition) { 178faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase loadTransition(transition, attrs); 179d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase if (transitionSet != null) { 180d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transitionSet.addTransition(transition); 181faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 182faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 183faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 184faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 185faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 186faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 187faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 188faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return transition; 189faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 190faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 191d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase private void getTargetIds(XmlPullParser parser, 192faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException { 193faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 194faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 195faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 196faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 197faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 198faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase ArrayList<Integer> targetIds = new ArrayList<Integer>(); 199faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 200faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 201faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 202faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 203faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 204faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 205faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 206faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 207faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (name.equals("target")) { 208faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TypedArray a = mContext.obtainStyledAttributes(attrs, 209d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase com.android.internal.R.styleable.TransitionTarget); 210d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int id = a.getResourceId( 211d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase com.android.internal.R.styleable.TransitionTarget_targetId, -1); 212faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (id >= 0) { 213faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase targetIds.add(id); 214faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 215faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 216faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 217faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 218faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 219faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int numTargets = targetIds.size(); 220faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (numTargets > 0) { 221d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase for (int i = 0; i < numTargets; ++i) { 222ff58f92a0a77ad849ba714b5adac96790eca0048Chet Haase transition.addTarget(targetIds.get(i)); 223faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 224faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 225faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 226faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 227faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private Transition loadTransition(Transition transition, AttributeSet attrs) 228faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throws Resources.NotFoundException { 229faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 230faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TypedArray a = 231faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase mContext.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Transition); 232faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase long duration = a.getInt(com.android.internal.R.styleable.Transition_duration, -1); 233faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (duration >= 0) { 234faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transition.setDuration(duration); 235faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 236d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase long startDelay = a.getInt(com.android.internal.R.styleable.Transition_startDelay, -1); 237d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase if (startDelay > 0) { 238d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase transition.setStartDelay(startDelay); 239faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 240faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase final int resID = 241faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0); 242faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (resID > 0) { 243faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transition.setInterpolator(AnimationUtils.loadInterpolator(mContext, resID)); 244faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 245faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase a.recycle(); 246faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return transition; 247faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 248faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 249faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 250faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // TransitionManager loading 251faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // 252faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 253faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private TransitionManager createTransitionManagerFromXml(XmlPullParser parser, 254faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase AttributeSet attrs, ViewGroup sceneRoot) throws XmlPullParserException, IOException { 255faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 256faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase // Make sure we are on a start tag. 257faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int type; 258faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase int depth = parser.getDepth(); 259faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TransitionManager transitionManager = null; 260faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 261faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 262faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase && type != XmlPullParser.END_DOCUMENT) { 263faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 264faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (type != XmlPullParser.START_TAG) { 265faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase continue; 266faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 267faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 268faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase String name = parser.getName(); 269faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (name.equals("transitionManager")) { 270faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transitionManager = new TransitionManager(); 271faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if (name.equals("transition") && (transitionManager != null)) { 272faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase loadTransition(attrs, sceneRoot, transitionManager); 273faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 274faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("Unknown scene name: " + parser.getName()); 275faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 276faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 277faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase return transitionManager; 278faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 279faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 280faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase private void loadTransition(AttributeSet attrs, ViewGroup sceneRoot, 281d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase TransitionManager transitionManager) throws Resources.NotFoundException { 282faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase 283faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase TypedArray a = mContext.obtainStyledAttributes(attrs, 284faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase com.android.internal.R.styleable.TransitionManager); 285d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int transitionId = a.getResourceId( 286faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase com.android.internal.R.styleable.TransitionManager_transition, -1); 287faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Scene fromScene = null, toScene = null; 288d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int fromId = a.getResourceId( 289faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase com.android.internal.R.styleable.TransitionManager_fromScene, -1); 290d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase if (fromId >= 0) fromScene = Scene.getSceneForLayout(sceneRoot, fromId, mContext); 291d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase int toId = a.getResourceId( 292faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase com.android.internal.R.styleable.TransitionManager_toScene, -1); 293d82c8ac4db7091d2e976af4c89a1734465d20cd2Chet Haase if (toId >= 0) toScene = Scene.getSceneForLayout(sceneRoot, toId, mContext); 294faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (transitionId >= 0) { 295faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase Transition transition = inflateTransition(transitionId); 296faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (transition != null) { 297faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (fromScene != null) { 298faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase if (toScene == null){ 299faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase throw new RuntimeException("No matching toScene for given fromScene " + 300faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase "for transition ID " + transitionId); 301faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else { 302faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transitionManager.setTransition(fromScene, toScene, transition); 303faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 304faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } else if (toId >= 0) { 305faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase transitionManager.setTransition(toScene, transition); 306faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 307faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 308faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 309faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase a.recycle(); 310faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase } 311faebd8f0795b7d275fb4e503533c8c0c4a9acc21Chet Haase} 312