TransitionInflater.java revision ae4925aede60914bcca5ed47d7ce868ae14313a2
18158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki/* 28158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Copyright (C) 2017 The Android Open Source Project 38158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 48158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Licensed under the Apache License, Version 2.0 (the "License"); 58158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * you may not use this file except in compliance with the License. 68158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * You may obtain a copy of the License at 78158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 88158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * http://www.apache.org/licenses/LICENSE-2.0 98158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Unless required by applicable law or agreed to in writing, software 118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * distributed under the License is distributed on an "AS IS" BASIS, 128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * See the License for the specific language governing permissions and 148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * limitations under the License. 158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakipackage android.support.transition; 188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.Context; 208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.Resources; 218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.TypedArray; 228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.content.res.XmlResourceParser; 238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.support.annotation.NonNull; 248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.support.v4.content.res.TypedArrayUtils; 258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.support.v4.util.ArrayMap; 268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.util.AttributeSet; 278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.util.Xml; 288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.InflateException; 298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.ViewGroup; 308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport org.xmlpull.v1.XmlPullParser; 328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport org.xmlpull.v1.XmlPullParserException; 338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport java.io.IOException; 358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport java.lang.reflect.Constructor; 368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 378158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki/** 388158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * This class inflates scenes and transitions from resource files. 398158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 408158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakipublic class TransitionInflater { 418158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 428158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private static final Class<?>[] CONSTRUCTOR_SIGNATURE = 438158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki new Class[]{Context.class, AttributeSet.class}; 448158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private static final ArrayMap<String, Constructor> CONSTRUCTORS = new ArrayMap<>(); 458158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 468158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private final Context mContext; 478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private TransitionInflater(@NonNull Context context) { 498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki mContext = context; 508158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Obtains the TransitionInflater from the given context. 548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public static TransitionInflater from(Context context) { 568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return new TransitionInflater(context); 578158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Loads a {@link Transition} object from a resource 618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @param resource The resource id of the transition to load 638158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @return The loaded Transition object 648158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @throws android.content.res.Resources.NotFoundException when the 658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition cannot be loaded 668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public Transition inflateTransition(int resource) { 688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki XmlResourceParser parser = mContext.getResources().getXml(resource); 698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null); 718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (XmlPullParserException e) { 728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException(e.getMessage(), e); 738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (IOException e) { 748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException( 758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.getPositionDescription() + ": " + e.getMessage(), e); 768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } finally { 778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.close(); 788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Loads a {@link TransitionManager} object from a resource 838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @param resource The resource id of the transition manager to load 858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @return The loaded TransitionManager object 868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @throws android.content.res.Resources.NotFoundException when the 878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition manager cannot be loaded 888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public TransitionManager inflateTransitionManager(int resource, ViewGroup sceneRoot) { 908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki XmlResourceParser parser = mContext.getResources().getXml(resource); 918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot); 938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (XmlPullParserException e) { 948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki InflateException ex = new InflateException(e.getMessage()); 958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ex.initCause(e); 968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw ex; 978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (IOException e) { 988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki InflateException ex = new InflateException( 998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.getPositionDescription() 1008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki + ": " + e.getMessage()); 1018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ex.initCause(e); 1028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw ex; 1038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } finally { 1048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.close(); 1058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 1098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Transition loading 1108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 1118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private Transition createTransitionFromXml(XmlPullParser parser, 1128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, Transition parent) 1138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throws XmlPullParserException, IOException { 1148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Transition transition = null; 1168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 1188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 1198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 1208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionSet transitionSet = (parent instanceof TransitionSet) 1228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ? (TransitionSet) parent : null; 1238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 1258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 1268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 1288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 1298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // TODO: Add more Transition types 1328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String name = parser.getName(); 1338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if ("fade".equals(name)) { 1348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = new Fade(mContext, attrs); 1358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("changeBounds".equals(name)) { 1368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = new ChangeBounds(mContext, attrs); 137ae4925aede60914bcca5ed47d7ce868ae14313a2Yuichi Araki } else if ("slide".equals(name)) { 138ae4925aede60914bcca5ed47d7ce868ae14313a2Yuichi Araki transition = new Slide(mContext, attrs); 1394c904b38c763179727b9b5ea7a80454630545663Yuichi Araki } else if ("explode".equals(name)) { 1404c904b38c763179727b9b5ea7a80454630545663Yuichi Araki transition = new Explode(mContext, attrs); 141fdfa819aa29e12734eb90101f5f40d2636a5f1aeYuichi Araki } else if ("changeImageTransform".equals(name)) { 142fdfa819aa29e12734eb90101f5f40d2636a5f1aeYuichi Araki transition = new ChangeImageTransform(mContext, attrs); 14350ce74b0963de66b294761c045428562d946b65aYuichi Araki } else if ("changeTransform".equals(name)) { 14450ce74b0963de66b294761c045428562d946b65aYuichi Araki transition = new ChangeTransform(mContext, attrs); 145f137a45c77ee2e753262dc3c5f691fdcfd75053bYuichi Araki } else if ("changeClipBounds".equals(name)) { 146f137a45c77ee2e753262dc3c5f691fdcfd75053bYuichi Araki transition = new ChangeClipBounds(mContext, attrs); 1478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("autoTransition".equals(name)) { 1488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = new AutoTransition(mContext, attrs); 1498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("transitionSet".equals(name)) { 1508158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = new TransitionSet(mContext, attrs); 1518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("transition".equals(name)) { 1528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = (Transition) createCustom(attrs, Transition.class, "transition"); 1538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("targets".equals(name)) { 1548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki getTargetIds(parser, attrs, parent); 1558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 1568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 1578158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transition != null) { 1598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (!parser.isEmptyElementTag()) { 1608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki createTransitionFromXml(parser, attrs, transition); 1618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transitionSet != null) { 1638158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionSet.addTransition(transition); 1648158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = null; 1658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if (parent != null) { 1668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException("Could not add transition to another transition."); 1678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return transition; 1728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private Object createCustom(AttributeSet attrs, Class expectedType, String tag) { 1758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String className = attrs.getAttributeValue(null, "class"); 1768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (className == null) { 1788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException(tag + " tag must have a 'class' attribute"); 1798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 1828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki synchronized (CONSTRUCTORS) { 1838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Constructor constructor = CONSTRUCTORS.get(className); 1848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (constructor == null) { 1858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class<?> c = mContext.getClassLoader().loadClass(className) 1868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki .asSubclass(expectedType); 1878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (c != null) { 1888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki constructor = c.getConstructor(CONSTRUCTOR_SIGNATURE); 1898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki constructor.setAccessible(true); 1908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki CONSTRUCTORS.put(className, constructor); 1918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki //noinspection ConstantConditions 1948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return constructor.newInstance(mContext, attrs); 1958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (Exception e) { 1978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException("Could not instantiate " + expectedType + " class " 1988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki + className, e); 1998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private void getTargetIds(XmlPullParser parser, 2038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException { 2048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 2068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 2078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 2088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 2108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 2118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 2138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 2148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String name = parser.getName(); 2178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (name.equals("target")) { 2188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_TARGET); 2198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int id = TypedArrayUtils.getNamedResourceId(a, parser, "targetId", 2208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.TARGET_ID, 0); 2218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String transitionName; 2228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (id != 0) { 2238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(id); 2248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((id = TypedArrayUtils.getNamedResourceId(a, parser, "excludeId", 2258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.EXCLUDE_ID, 0)) != 0) { 2268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(id, true); 2278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser, "targetName", 2288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.TARGET_NAME)) != null) { 2298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(transitionName); 2308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser, 2318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "excludeName", Styleable.TransitionTarget.EXCLUDE_NAME)) != null) { 2328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(transitionName, true); 2338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 2348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String className = TypedArrayUtils.getNamedString(a, parser, 2358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "excludeClass", Styleable.TransitionTarget.EXCLUDE_CLASS); 2368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 2378158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (className != null) { 2388158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class clazz = Class.forName(className); 2398158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(clazz, true); 2408158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((className = TypedArrayUtils.getNamedString(a, parser, 2418158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "targetClass", Styleable.TransitionTarget.TARGET_CLASS)) != null) { 2428158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class clazz = Class.forName(className); 2438158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(clazz); 2448158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2458158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (ClassNotFoundException e) { 2468158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 2478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Could not create " + className, e); 2488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2508158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 2518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 2528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 2538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2578158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 2588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // TransitionManager loading 2598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 2608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private TransitionManager createTransitionManagerFromXml(XmlPullParser parser, 2628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, ViewGroup sceneRoot) throws XmlPullParserException, IOException { 2638158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2648158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 2658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 2668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 2678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionManager transitionManager = null; 2688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 2708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 2718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 2738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 2748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String name = parser.getName(); 2778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (name.equals("transitionManager")) { 2788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager = new TransitionManager(); 2798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if (name.equals("transition") && (transitionManager != null)) { 2808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki loadTransition(attrs, parser, sceneRoot, transitionManager); 2818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 2828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 2838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return transitionManager; 2868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private void loadTransition(AttributeSet attrs, XmlPullParser parser, ViewGroup sceneRoot, 2898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionManager transitionManager) throws Resources.NotFoundException { 2908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_MANAGER); 2928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int transitionId = TypedArrayUtils.getNamedResourceId(a, parser, "transition", 2938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.TRANSITION, -1); 2948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int fromId = TypedArrayUtils.getNamedResourceId(a, parser, "fromScene", 2958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.FROM_SCENE, -1); 2968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Scene fromScene = (fromId < 0) ? null : Scene.getSceneForLayout(sceneRoot, fromId, 2978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki mContext); 2988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int toId = TypedArrayUtils.getNamedResourceId(a, parser, "toScene", 2998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.TO_SCENE, -1); 3008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext); 3018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transitionId >= 0) { 3038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Transition transition = inflateTransition(transitionId); 3048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transition != null) { 3058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (toScene == null) { 3068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("No toScene for transition ID " + transitionId); 3078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (fromScene == null) { 3098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager.setTransition(toScene, transition); 3108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 3118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager.setTransition(fromScene, toScene, transition); 3128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 3168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki} 319