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 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.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.util.AttributeSet; 248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.util.Xml; 258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.InflateException; 268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport android.view.ViewGroup; 278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 284d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.annotation.NonNull; 294d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.collection.ArrayMap; 304d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikasimport androidx.core.content.res.TypedArrayUtils; 314d1d6a17310a57807dabb3f404715cfe43a90ed0Aurimas Liutikas 328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport org.xmlpull.v1.XmlPullParser; 338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport org.xmlpull.v1.XmlPullParserException; 348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport java.io.IOException; 368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakiimport java.lang.reflect.Constructor; 378158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 388158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki/** 398158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * This class inflates scenes and transitions from resource files. 408158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 418158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Arakipublic class TransitionInflater { 428158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 438158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private static final Class<?>[] CONSTRUCTOR_SIGNATURE = 448158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki new Class[]{Context.class, AttributeSet.class}; 458158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private static final ArrayMap<String, Constructor> CONSTRUCTORS = new ArrayMap<>(); 468158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private final Context mContext; 488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private TransitionInflater(@NonNull Context context) { 508158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki mContext = context; 518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Obtains the TransitionInflater from the given context. 558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public static TransitionInflater from(Context context) { 578158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return new TransitionInflater(context); 588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Loads a {@link Transition} object from a resource 628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 638158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @param resource The resource id of the transition to load 648158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @return The loaded Transition object 658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @throws android.content.res.Resources.NotFoundException when the 668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition cannot be loaded 678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public Transition inflateTransition(int resource) { 698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki XmlResourceParser parser = mContext.getResources().getXml(resource); 708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return createTransitionFromXml(parser, Xml.asAttributeSet(parser), null); 728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (XmlPullParserException e) { 738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException(e.getMessage(), e); 748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (IOException e) { 758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException( 768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.getPositionDescription() + ": " + e.getMessage(), e); 778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } finally { 788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.close(); 798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki /** 838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * Loads a {@link TransitionManager} object from a resource 848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * 858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @param resource The resource id of the transition manager to load 868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @return The loaded TransitionManager object 878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * @throws android.content.res.Resources.NotFoundException when the 888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki * transition manager cannot be loaded 898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki */ 908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki public TransitionManager inflateTransitionManager(int resource, ViewGroup sceneRoot) { 918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki XmlResourceParser parser = mContext.getResources().getXml(resource); 928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return createTransitionManagerFromXml(parser, Xml.asAttributeSet(parser), sceneRoot); 948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (XmlPullParserException e) { 958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki InflateException ex = new InflateException(e.getMessage()); 968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ex.initCause(e); 978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw ex; 988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (IOException e) { 998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki InflateException ex = new InflateException( 1008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.getPositionDescription() 1018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki + ": " + e.getMessage()); 1028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ex.initCause(e); 1038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw ex; 1048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } finally { 1058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki parser.close(); 1068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 1108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Transition loading 1118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 1128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private Transition createTransitionFromXml(XmlPullParser parser, 1138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, Transition parent) 1148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throws XmlPullParserException, IOException { 1158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Transition transition = null; 1178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 1198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 1208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 1218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionSet transitionSet = (parent instanceof TransitionSet) 1238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki ? (TransitionSet) parent : null; 1248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 1268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 1278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 1298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 1308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 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); 149913cfb35ee8a1fc3223c4f98bd1e22182b035186Yuichi Araki } else if ("changeScroll".equals(name)) { 150913cfb35ee8a1fc3223c4f98bd1e22182b035186Yuichi Araki transition = new ChangeScroll(mContext, attrs); 1518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("transitionSet".equals(name)) { 1528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = new TransitionSet(mContext, attrs); 1538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("transition".equals(name)) { 1548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = (Transition) createCustom(attrs, Transition.class, "transition"); 1558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ("targets".equals(name)) { 1568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki getTargetIds(parser, attrs, parent); 157142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } else if ("arcMotion".equals(name)) { 158142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki if (parent == null) { 159142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki throw new RuntimeException("Invalid use of arcMotion element"); 160142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } 161142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki parent.setPathMotion(new ArcMotion(mContext, attrs)); 162142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } else if ("pathMotion".equals(name)) { 163142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki if (parent == null) { 164142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki throw new RuntimeException("Invalid use of pathMotion element"); 165142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } 166142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki parent.setPathMotion((PathMotion) createCustom(attrs, PathMotion.class, 167142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki "pathMotion")); 168142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } else if ("patternPathMotion".equals(name)) { 169142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki if (parent == null) { 170142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki throw new RuntimeException("Invalid use of patternPathMotion element"); 171142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki } 172142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Araki parent.setPathMotion(new PatternPathMotion(mContext, attrs)); 1738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 1748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 1758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transition != null) { 1778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (!parser.isEmptyElementTag()) { 1788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki createTransitionFromXml(parser, attrs, transition); 1798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transitionSet != null) { 1818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionSet.addTransition(transition); 1828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition = null; 1838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if (parent != null) { 1848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException("Could not add transition to another transition."); 1858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return transition; 1908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private Object createCustom(AttributeSet attrs, Class expectedType, String tag) { 1938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String className = attrs.getAttributeValue(null, "class"); 1948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (className == null) { 1968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException(tag + " tag must have a 'class' attribute"); 1978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 1988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 1998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 2008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki synchronized (CONSTRUCTORS) { 2018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Constructor constructor = CONSTRUCTORS.get(className); 2028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (constructor == null) { 203df81a97346c6617a3de1f54d7d13eecd5a3200eeYuichi Araki @SuppressWarnings("unchecked") 2048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class<?> c = mContext.getClassLoader().loadClass(className) 2058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki .asSubclass(expectedType); 2068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (c != null) { 2078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki constructor = c.getConstructor(CONSTRUCTOR_SIGNATURE); 2088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki constructor.setAccessible(true); 2098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki CONSTRUCTORS.put(className, constructor); 2108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki //noinspection ConstantConditions 2138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return constructor.newInstance(mContext, attrs); 2148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (Exception e) { 2168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new InflateException("Could not instantiate " + expectedType + " class " 2178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki + className, e); 2188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private void getTargetIds(XmlPullParser parser, 2228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, Transition transition) throws XmlPullParserException, IOException { 2238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 2258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 2268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 2278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 2298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 2308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 2328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 2338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String name = parser.getName(); 2368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (name.equals("target")) { 2378158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_TARGET); 2388158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int id = TypedArrayUtils.getNamedResourceId(a, parser, "targetId", 2398158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.TARGET_ID, 0); 2408158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String transitionName; 2418158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (id != 0) { 2428158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(id); 2438158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((id = TypedArrayUtils.getNamedResourceId(a, parser, "excludeId", 2448158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.EXCLUDE_ID, 0)) != 0) { 2458158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(id, true); 2468158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser, "targetName", 2478158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionTarget.TARGET_NAME)) != null) { 2488158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(transitionName); 2498158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((transitionName = TypedArrayUtils.getNamedString(a, parser, 2508158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "excludeName", Styleable.TransitionTarget.EXCLUDE_NAME)) != null) { 2518158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(transitionName, true); 2528158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 2538158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String className = TypedArrayUtils.getNamedString(a, parser, 2548158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "excludeClass", Styleable.TransitionTarget.EXCLUDE_CLASS); 2558158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki try { 2568158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (className != null) { 2578158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class clazz = Class.forName(className); 2588158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.excludeTarget(clazz, true); 2598158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if ((className = TypedArrayUtils.getNamedString(a, parser, 2608158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki "targetClass", Styleable.TransitionTarget.TARGET_CLASS)) != null) { 2618158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Class clazz = Class.forName(className); 2628158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transition.addTarget(clazz); 2638158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2648158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } catch (ClassNotFoundException e) { 2658158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 2668158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Could not create " + className, e); 2678158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2688158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2698158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 2708158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 2718158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 2728158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2738158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2748158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2758158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2768158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 2778158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // TransitionManager loading 2788158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // 2798158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2808158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private TransitionManager createTransitionManagerFromXml(XmlPullParser parser, 2818158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki AttributeSet attrs, ViewGroup sceneRoot) throws XmlPullParserException, IOException { 2828158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2838158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki // Make sure we are on a start tag. 2848158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int type; 2858158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int depth = parser.getDepth(); 2868158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionManager transitionManager = null; 2878158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2888158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) 2898158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki && type != XmlPullParser.END_DOCUMENT) { 2908158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2918158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (type != XmlPullParser.START_TAG) { 2928158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki continue; 2938158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 2948158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 2958158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki String name = parser.getName(); 2968158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (name.equals("transitionManager")) { 2978158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager = new TransitionManager(); 2988158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else if (name.equals("transition") && (transitionManager != null)) { 2998158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki loadTransition(attrs, parser, sceneRoot, transitionManager); 3008158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 3018158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("Unknown scene name: " + parser.getName()); 3028158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3038158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3048158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki return transitionManager; 3058158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3068158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3078158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki private void loadTransition(AttributeSet attrs, XmlPullParser parser, ViewGroup sceneRoot, 3088158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TransitionManager transitionManager) throws Resources.NotFoundException { 3098158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3108158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki TypedArray a = mContext.obtainStyledAttributes(attrs, Styleable.TRANSITION_MANAGER); 3118158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int transitionId = TypedArrayUtils.getNamedResourceId(a, parser, "transition", 3128158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.TRANSITION, -1); 3138158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int fromId = TypedArrayUtils.getNamedResourceId(a, parser, "fromScene", 3148158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.FROM_SCENE, -1); 3158158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Scene fromScene = (fromId < 0) ? null : Scene.getSceneForLayout(sceneRoot, fromId, 3168158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki mContext); 3178158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki int toId = TypedArrayUtils.getNamedResourceId(a, parser, "toScene", 3188158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Styleable.TransitionManager.TO_SCENE, -1); 3198158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext); 3208158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3218158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transitionId >= 0) { 3228158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki Transition transition = inflateTransition(transitionId); 3238158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (transition != null) { 3248158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (toScene == null) { 3258158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki throw new RuntimeException("No toScene for transition ID " + transitionId); 3268158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3278158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki if (fromScene == null) { 3288158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager.setTransition(toScene, transition); 3298158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } else { 3308158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki transitionManager.setTransition(fromScene, toScene, transition); 3318158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3328158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3338158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3348158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki a.recycle(); 3358158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki } 3368158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki 3378158051cdfef95fc1f22b56bba93b9c610f5ecb1Yuichi Araki} 338