/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package androidx.constraintlayout.motion.widget; import android.content.Context; import android.content.res.XmlResourceParser; import android.util.Log; import android.util.Xml; import androidx.constraintlayout.widget.ConstraintAttribute; import androidx.constraintlayout.widget.ConstraintLayout; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; /** * The parses the KeyFrame structure in a MotionScene xml * */ public class KeyFrames { public static final int UNSET = ConstraintLayout.LayoutParams.UNSET; private static final String CUSTOM_METHOD = "CustomMethod"; private static final String CUSTOM_ATTRIBUTE = "CustomAttribute"; private HashMap> mFramesMap = new HashMap>(); static HashMap> sKeyMakers = new HashMap<>(); private static final String TAG = "KeyFrames"; static { try { sKeyMakers.put(KeyAttributes.NAME, KeyAttributes.class.getConstructor()); sKeyMakers.put(KeyPosition.NAME, KeyPosition.class.getConstructor()); sKeyMakers.put(KeyCycle.NAME, KeyCycle.class.getConstructor()); sKeyMakers.put(KeyTimeCycle.NAME, KeyTimeCycle.class.getConstructor()); sKeyMakers.put(KeyTrigger.NAME, KeyTrigger.class.getConstructor()); } catch (NoSuchMethodException e) { Log.e(TAG, "unable to load", e); } } /** * Add a key to this set of keyframes * @param key */ public void addKey(Key key) { if (!mFramesMap.containsKey(key.mTargetId)) { mFramesMap.put(key.mTargetId, new ArrayList<>()); } ArrayList frames = mFramesMap.get(key.mTargetId); if (frames != null) { frames.add(key); } } public KeyFrames() { } public KeyFrames(Context context, XmlPullParser parser) { String tagName = null; try { Key key = null; for (int eventType = parser.getEventType(); eventType != XmlResourceParser.END_DOCUMENT; eventType = parser.next()) { switch (eventType) { case XmlResourceParser.START_DOCUMENT: break; case XmlResourceParser.START_TAG: tagName = parser.getName(); if (sKeyMakers.containsKey(tagName)) { switch (tagName) { case KeyAttributes.NAME: key = new KeyAttributes(); break; case KeyPosition.NAME: key = new KeyPosition(); break; case KeyCycle.NAME: key = new KeyCycle(); break; case KeyTimeCycle.NAME: key = new KeyTimeCycle(); break; case KeyTrigger.NAME: key = new KeyTrigger(); break; default: throw new NullPointerException( "Key " + tagName + " not found"); } key.load(context, Xml.asAttributeSet(parser)); addKey(key); } else if (tagName.equalsIgnoreCase(CUSTOM_ATTRIBUTE)) { if (key != null && key.mCustomConstraints != null) { ConstraintAttribute.parse(context, parser, key.mCustomConstraints); } } else if (tagName.equalsIgnoreCase(CUSTOM_METHOD)) { if (key != null && key.mCustomConstraints != null) { ConstraintAttribute.parse(context, parser, key.mCustomConstraints); } } break; case XmlResourceParser.END_TAG: if ("KeyFrameSet".equals(parser.getName())) { return; } break; case XmlResourceParser.TEXT: break; } } } catch (XmlPullParserException e) { Log.e(TAG, "Error parsing XML resource", e); } catch (IOException e) { Log.e(TAG, "Error parsing XML resource", e); } } /** * Do not filter the set by matches * @param motionController */ public void addAllFrames(MotionController motionController) { ArrayList list = mFramesMap.get(UNSET); if (list != null) { motionController.addKeys(list); } } /** * add the key frames to the motion controller * @param motionController */ public void addFrames(MotionController motionController) { ArrayList list = mFramesMap.get(motionController.mId); if (list != null) { motionController.addKeys(list); } list = mFramesMap.get(UNSET); if (list != null) { for (Key key : list) { String tag = ((ConstraintLayout.LayoutParams) motionController.mView.getLayoutParams()).constraintTag; if (key.matches(tag)) { motionController.addKey(key); } } } } static String name(int viewId, Context context) { return context.getResources().getResourceEntryName(viewId); } public Set getKeys() { return mFramesMap.keySet(); } /** * Get the list of keyframes given and ID * @param id * @return */ public ArrayList getKeyFramesForView(int id) { return mFramesMap.get(id); } }