1e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui/* 2e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Copyright (C) 2014 The Android Open Source Project 3e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * 4e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * in compliance with the License. You may obtain a copy of the License at 6e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * 7e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * http://www.apache.org/licenses/LICENSE-2.0 8e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * 9e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * Unless required by applicable law or agreed to in writing, software distributed under the License 10e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * or implied. See the License for the specific language governing permissions and limitations under 12e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * the License. 13e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui */ 14e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 15e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuipackage android.graphics.drawable; 16e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 17e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.animation.Animator; 1818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport android.animation.Animator.AnimatorListener; 19e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.animation.AnimatorInflater; 2083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghuiimport android.animation.AnimatorListenerAdapter; 211588f0ff54b88240b55eeaba97e67f0f1dee5f92ztenghuiimport android.animation.AnimatorSet; 2218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport android.animation.ObjectAnimator; 23766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.PropertyValuesHolder; 24766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.TimeInterpolator; 25766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.animation.ValueAnimator; 2606cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.annotation.NonNull; 27d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viveretteimport android.annotation.Nullable; 28ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.app.ActivityThread; 29ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.app.Application; 30ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport android.content.pm.ActivityInfo.Config; 3106cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.content.res.ColorStateList; 32e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.Resources; 33e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.Resources.Theme; 34e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.content.res.TypedArray; 35e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.Canvas; 36e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.ColorFilter; 3787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets; 3806cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.graphics.Outline; 39f10d08a3d4968d3dfb4324959e33ebb691899edaTeng-Hui Zhuimport android.graphics.PixelFormat; 4006cd7dce24876b54870f9ef3831237f8298773a9Alan Viveretteimport android.graphics.PorterDuff; 41e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.graphics.Rect; 42ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liuimport android.os.Build; 436f6578e81c1df207da47e2e1337382341f271206Chet Haaseimport android.util.ArrayMap; 44e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.AttributeSet; 4544027214d4f2154ebc9265912933bac282be3bb4Doris Liuimport android.util.IntArray; 46e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.Log; 47766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.LongArray; 48766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.PathParser; 49792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liuimport android.util.Property; 50766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.util.TimeUtils; 51766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.Choreographer; 52766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.DisplayListCanvas; 53766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.RenderNode; 54766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport android.view.RenderNodeAnimatorSetHelper; 55dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viveretteimport android.view.View; 56e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 57e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport com.android.internal.R; 58766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport com.android.internal.util.VirtualRefBasePtr; 59299659ddb7e0c34ca094abe485bcd0989727fc07John Reck 60e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport org.xmlpull.v1.XmlPullParser; 61e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport org.xmlpull.v1.XmlPullParserException; 62e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 63e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport java.io.IOException; 64766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuimport java.lang.ref.WeakReference; 65e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport java.util.ArrayList; 66e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 6718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhuimport dalvik.annotation.optimization.FastNative; 6818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu 69e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui/** 707d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * This class animates properties of a {@link android.graphics.drawable.VectorDrawable} with 717d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * animations defined using {@link android.animation.ObjectAnimator} or 727d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * {@link android.animation.AnimatorSet}. 737e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p> 747d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Starting from API 25, AnimatedVectorDrawable runs on RenderThread (as opposed to on UI thread for 757d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * earlier APIs). This means animations in AnimatedVectorDrawable can remain smooth even when there 767d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * is heavy workload on the UI thread. Note: If the UI thread is unresponsive, RenderThread may 777d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * continue animating until the UI thread is capable of pushing another frame. Therefore, it is not 787d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * possible to precisely coordinate a RenderThread-enabled AnimatedVectorDrawable with UI thread 797d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * animations. Additionally, 807d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * {@link android.graphics.drawable.Animatable2.AnimationCallback#onAnimationEnd(Drawable)} will be 817d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * called the frame after the AnimatedVectorDrawable finishes on the RenderThread. 827e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p> 837e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p> 847d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * AnimatedVectorDrawable can be defined in either <a href="#ThreeXML">three separate XML files</a>, 857d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * or <a href="#OneXML">one XML</a>. 867e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p> 877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="ThreeXML"></a> 887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <h3>Define an AnimatedVectorDrawable in three separate XML files</h3> 897d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <ul> 907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="VDExample"></a> 917d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for the VectorDrawable containing properties to be animated</h4> 927d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <p> 9318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * Animations can be performed on the animatable attributes in 9418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * {@link android.graphics.drawable.VectorDrawable}. These attributes will be animated by 9518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * {@link android.animation.ObjectAnimator}. The ObjectAnimator's target can be the root element, 9618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * a group element or a path element. The targeted elements need to be named uniquely within 9718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * the same VectorDrawable. Elements without animation do not need to be named. 9818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </p> 9918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <p> 10018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * Here are all the animatable attributes in {@link android.graphics.drawable.VectorDrawable}: 10118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <table border="2" align="center" cellpadding="5"> 10218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <thead> 10318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 10418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <th>Element Name</th> 10518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <th>Animatable attribute name</th> 10618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 10718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </thead> 10818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 10918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td><vector></td> 11018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>alpha</td> 11118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 11218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 11318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td rowspan="7"><group></td> 11418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>rotation</td> 11518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 11618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 11718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>pivotX</td> 11818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 11918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 12018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>pivotY</td> 12118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 12218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 12318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>scaleX</td> 12418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 12518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 12618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>scaleY</td> 12718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 12818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 12918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>translateX</td> 13018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 13118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 13218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>translateY</td> 13318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 13418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 13518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td rowspan="8"><path></td> 13618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>pathData</td> 13718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 13818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 13918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>fillColor</td> 14018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 14118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 14218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>strokeColor</td> 14318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 14418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 14518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>strokeWidth</td> 14618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 14718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 14818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>strokeAlpha</td> 14918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 15018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 15118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>fillAlpha</td> 15218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 15318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 15418ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>trimPathStart</td> 15518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 15618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 15718ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>trimPathOffset</td> 15818ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 15918ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <tr> 16018ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td><clip-path></td> 16118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <td>pathData</td> 16218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </tr> 16318ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * </table> 1647d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </p> 1657d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is 1667d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * referred to by its file name (not including file suffix) in the 1677d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a href="AVDExample">AnimatedVectorDrawable XML example</a>. 1687e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre> 169a95c8abb366d9c39450513335f550b56da13b30aztenghui * <vector xmlns:android="http://schemas.android.com/apk/res/android" 170a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:height="64dp" 171a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:width="64dp" 172a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:viewportHeight="600" 173a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:viewportWidth="600" > 1747e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <group 1757e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:name="rotationGroup" 1767e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:pivotX="300.0" 1777e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:pivotY="300.0" 1787e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:rotation="45.0" > 1797e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <path 1807e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:name="v" 181a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:fillColor="#000000" 1827e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> 1837e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </group> 1847e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </vector> 1857e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </pre></li> 1867d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * 1877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="AVDExample"></a> 1887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for AnimatedVectorDrawable</h4> 1897e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p> 1907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target 19118ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * element(s). The target element can specify its target by android:name attribute, and link the 19218ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * target with the proper ObjectAnimator or AnimatorSet by android:animation attribute. 1937e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p> 1947d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * The following code sample defines an AnimatedVectorDrawable. Note that the names refer to the 1957d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * groups and paths in the <a href="#VDExample">VectorDrawable XML above</a>. 1967e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre> 1977e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" 1987d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * android:drawable="@drawable/vectordrawable" > 1997e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <target 2007e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:name="rotationGroup" 2017e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:animation="@anim/rotation" /> 2027e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <target 2037e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:name="v" 2047e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:animation="@anim/path_morph" /> 2057e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </animated-vector> 2067d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre> 2077d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </li> 2087d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * 2097d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <li><h4>XML for Animations defined using ObjectAnimator or AnimatorSet</h4> 2107e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <p> 2117d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * From the previous <a href="#AVDExample">example of AnimatedVectorDrawable</a>, two animations 2127d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * were used: rotation.xml and path_morph.xml. 2137e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </p> 2147d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * rotation.xml rotates the target group from 0 degree to 360 degrees over 6000ms: 2157e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre> 2167e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <objectAnimator 2177e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:duration="6000" 2187e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:propertyName="rotation" 2197e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:valueFrom="0" 2207e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:valueTo="360" /> 2217d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre> 2227d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * 2237d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * path_morph.xml morphs the path from one shape into the other. Note that the paths must be 2247d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * compatible for morphing. Specifically, the paths must have the same commands, in the same order, 2257d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * and must have the same number of parameters for each command. It is recommended to store path 2267d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * strings as string resources for reuse. 2277e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <pre> 2287e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <set xmlns:android="http://schemas.android.com/apk/res/android"> 2297e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * <objectAnimator 2307e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:duration="3000" 2317e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:propertyName="pathData" 2327d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" 2337e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" 2347e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * android:valueType="pathType"/> 2357e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * </set> 2367d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </pre> 2377d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </ul> 2387d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <a name="OneXML"></a> 2397d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <h3>Define an AnimatedVectorDrawable all in one XML file</h3> 240d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <p> 2417d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Since the AAPT tool supports a new format that bundles several related XML files together, we can 2427d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * merge the XML files from the previous examples into one XML file: 243d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </p> 244d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <pre> 24518ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" 24618ad5f43685489e0086dce74f2bfcca9ba39daa3Teng-Hui Zhu * xmlns:aapt="http://schemas.android.com/aapt" > 247d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <aapt:attr name="android:drawable"> 248d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <vector 249d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:height="64dp" 250d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:width="64dp" 251d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:viewportHeight="600" 252d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:viewportWidth="600" > 253d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <group 254d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:name="rotationGroup" 255d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:pivotX="300.0" 256d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:pivotY="300.0" 257d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:rotation="45.0" > 258d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <path 259d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:name="v" 260d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:fillColor="#000000" 261d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> 262d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </group> 263d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </vector> 264d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </aapt:attr> 265d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * 266d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <target android:name="rotationGroup"> * 267d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <aapt:attr name="android:animation"> 268d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <objectAnimator 269d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:duration="6000" 270d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:propertyName="rotation" 271d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:valueFrom="0" 272d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:valueTo="360" /> 273d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </aapt:attr> 274d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </target> 275d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * 276d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <target android:name="v" > 277d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <aapt:attr name="android:animation"> 278d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <set> 279d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * <objectAnimator 280d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:duration="3000" 281d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:propertyName="pathData" 2827d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z" 283d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z" 284d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * android:valueType="pathType"/> 285d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </set> 286d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </aapt:attr> 287d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </target> 288d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </animated-vector> 289d64255f61db30934e293adab2a5a8ac9eeea0b98Teng-Hui Zhu * </pre> 290e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui * 2917e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawable_drawable 2927e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name 2937e7ea9da6785a8345feffb754ddcb55b16cf69c9ztenghui * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation 294e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui */ 29583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghuipublic class AnimatedVectorDrawable extends Drawable implements Animatable2 { 296d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette private static final String LOGTAG = "AnimatedVectorDrawable"; 297e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 298e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui private static final String ANIMATED_VECTOR = "animated-vector"; 299e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui private static final String TARGET = "target"; 300e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 301e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; 302e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 303d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** Local, mutable animator set. */ 304718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu private VectorDrawableAnimator mAnimatorSet; 305d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 306d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** 307d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * The resources against which this drawable was created. Used to attempt 308d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * to inflate animators if applyTheme() doesn't get called. 309d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette */ 310d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette private Resources mRes; 311d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 3126f6578e81c1df207da47e2e1337382341f271206Chet Haase private AnimatedVectorDrawableState mAnimatedVectorState; 3136f6578e81c1df207da47e2e1337382341f271206Chet Haase 31428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu /** The animator set that is parsed from the xml. */ 31528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private AnimatorSet mAnimatorSetFromXml = null; 316d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 3176f6578e81c1df207da47e2e1337382341f271206Chet Haase private boolean mMutated; 318e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 31983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui /** Use a internal AnimatorListener to support callbacks during animation events. */ 32083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui private ArrayList<Animatable2.AnimationCallback> mAnimationCallbacks = null; 32183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui private AnimatorListener mAnimatorListener = null; 32283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 323e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public AnimatedVectorDrawable() { 32417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette this(null, null); 325e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 326e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 32717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) { 32817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res); 329718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu mAnimatorSet = new VectorDrawableAnimatorRT(this); 330d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mRes = res; 331e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 333e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 3346f6578e81c1df207da47e2e1337382341f271206Chet Haase public Drawable mutate() { 3356f6578e81c1df207da47e2e1337382341f271206Chet Haase if (!mMutated && super.mutate() == this) { 336d2f50c78c3c5205d6b28b7079d2f845c3d9dc0b3ztenghui mAnimatedVectorState = new AnimatedVectorDrawableState( 33795080637db69ffa4f31f18f32878ddd2457e6857ztenghui mAnimatedVectorState, mCallback, mRes); 3386f6578e81c1df207da47e2e1337382341f271206Chet Haase mMutated = true; 3396f6578e81c1df207da47e2e1337382341f271206Chet Haase } 3406f6578e81c1df207da47e2e1337382341f271206Chet Haase return this; 3416f6578e81c1df207da47e2e1337382341f271206Chet Haase } 3426f6578e81c1df207da47e2e1337382341f271206Chet Haase 343727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette /** 344727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette * @hide 345727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette */ 346727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette public void clearMutated() { 347727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette super.clearMutated(); 348d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (mAnimatedVectorState.mVectorDrawable != null) { 349d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimatedVectorState.mVectorDrawable.clearMutated(); 350d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 351727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mMutated = false; 352727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette } 353727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette 354ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu /** 355ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu * In order to avoid breaking old apps, we only throw exception on invalid VectorDrawable 356b34cbedb4e36f184232d7f40b093bdc9fd0cd752Dianne Hackborn * animations for apps targeting N and later. For older apps, we ignore (i.e. quietly skip) 357ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu * these animations. 358ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu * 359ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu * @return whether invalid animations for vector drawable should be ignored. 360ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu */ 361ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu private static boolean shouldIgnoreInvalidAnimation() { 362ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu Application app = ActivityThread.currentApplication(); 363ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu if (app == null || app.getApplicationInfo() == null) { 364ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu return true; 365ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } 366ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu if (app.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { 367ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu return true; 368ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } 369ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu return false; 370ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } 371ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu 3726f6578e81c1df207da47e2e1337382341f271206Chet Haase @Override 373e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public ConstantState getConstantState() { 37498916d146afe2ff25a439603f7d9559e74a790caztenghui mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations(); 3756f6578e81c1df207da47e2e1337382341f271206Chet Haase return mAnimatedVectorState; 376e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 377e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 378e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 379ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette public @Config int getChangingConfigurations() { 380e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations(); 38198916d146afe2ff25a439603f7d9559e74a790caztenghui } 38298916d146afe2ff25a439603f7d9559e74a790caztenghui 3837d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu /** 3847d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * Draws the AnimatedVectorDrawable into the given canvas. 3857d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <p> 3867d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * <strong>Note:</strong> Calling this method with a software canvas when the 3877d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * AnimatedVectorDrawable is being animated on RenderThread (for API 25 and later) may yield 3887d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * outdated result, as the UI thread is not guaranteed to be in sync with RenderThread on 3897d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * VectorDrawable's property changes during RenderThread animations. 3907d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * </p> 3917d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * 3927d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * @param canvas The canvas to draw into 3937d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu */ 39498916d146afe2ff25a439603f7d9559e74a790caztenghui @Override 395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void draw(Canvas canvas) { 396126df850ce6b5f8a355534eb09235e22995f0116Doris Liu if (!canvas.isHardwareAccelerated() && mAnimatorSet instanceof VectorDrawableAnimatorRT) { 397126df850ce6b5f8a355534eb09235e22995f0116Doris Liu // If we have SW canvas and the RT animation is waiting to start, We need to fallback 398126df850ce6b5f8a355534eb09235e22995f0116Doris Liu // to UI thread animation for AVD. 399126df850ce6b5f8a355534eb09235e22995f0116Doris Liu if (!mAnimatorSet.isRunning() && 400126df850ce6b5f8a355534eb09235e22995f0116Doris Liu ((VectorDrawableAnimatorRT) mAnimatorSet).mPendingAnimationActions.size() > 0) { 401853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu fallbackOntoUI(); 402126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } 403126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } 40428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSet.onDraw(canvas); 405e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mAnimatedVectorState.mVectorDrawable.draw(canvas); 406e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 407e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 408e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 409e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui protected void onBoundsChange(Rect bounds) { 410e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mAnimatedVectorState.mVectorDrawable.setBounds(bounds); 411e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 412e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 413e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 41406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette protected boolean onStateChange(int[] state) { 41506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette return mAnimatedVectorState.mVectorDrawable.setState(state); 41606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 41706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 41806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 4190b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette protected boolean onLevelChange(int level) { 42006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette return mAnimatedVectorState.mVectorDrawable.setLevel(level); 42106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 42206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 42306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 424dfa4646eca54511a28f2c61e1f4b9c697e05a913Alan Viverette public boolean onLayoutDirectionChanged(@View.ResolvedLayoutDir int layoutDirection) { 425a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette return mAnimatedVectorState.mVectorDrawable.setLayoutDirection(layoutDirection); 426a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette } 427a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette 4281af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu /** 4297d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * For API 25 and later, AnimatedVectorDrawable runs on RenderThread. Therefore, when the 4307d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * root alpha is being animated, this getter does not guarantee to return an up-to-date alpha 4317d76fc4433e0eedf10b0a87860565ddc93e8ef2eDoris Liu * value. 4321af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu * 4331af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu * @return the containing vector drawable's root alpha value. 4341af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu */ 435a12962207155305da44b5a1b8fb9acaed358c14cAlan Viverette @Override 436e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public int getAlpha() { 437e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mAnimatedVectorState.mVectorDrawable.getAlpha(); 438e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 439e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 440e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 441e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setAlpha(int alpha) { 442e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mAnimatedVectorState.mVectorDrawable.setAlpha(alpha); 443e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 444e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 445e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 446e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setColorFilter(ColorFilter colorFilter) { 447e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter); 448e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 449e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 450e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 4511af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu public ColorFilter getColorFilter() { 4521af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu return mAnimatedVectorState.mVectorDrawable.getColorFilter(); 4531af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu } 4541af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu 4551af03b1d5319921c9f898103353f2646975ab0afTeng-Hui Zhu @Override 45606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public void setTintList(ColorStateList tint) { 45706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.setTintList(tint); 45806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 45906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 46006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 46106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public void setHotspot(float x, float y) { 46206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.setHotspot(x, y); 46306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 46406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 46506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 46606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public void setHotspotBounds(int left, int top, int right, int bottom) { 46706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.setHotspotBounds(left, top, right, bottom); 46806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 46906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 47006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 47106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public void setTintMode(PorterDuff.Mode tintMode) { 47206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode); 47306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 47406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 47506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 47606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public boolean setVisible(boolean visible, boolean restart) { 477d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu if (mAnimatorSet.isInfinite() && mAnimatorSet.isStarted()) { 478d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu if (visible) { 479d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu // Resume the infinite animation when the drawable becomes visible again. 480d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mAnimatorSet.resume(); 481d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } else { 482d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu // Pause the infinite animation once the drawable is no longer visible. 483d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mAnimatorSet.pause(); 484d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 485d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 48606cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart); 48706cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette return super.setVisible(visible, restart); 48806cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 48906cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 49006cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 49106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public boolean isStateful() { 49206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette return mAnimatedVectorState.mVectorDrawable.isStateful(); 49306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 49406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 49506cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 496e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public int getOpacity() { 497f10d08a3d4968d3dfb4324959e33ebb691899edaTeng-Hui Zhu return PixelFormat.TRANSLUCENT; 498e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 499e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 500e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 501e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public int getIntrinsicWidth() { 502e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth(); 503e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 504e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 505e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 506e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public int getIntrinsicHeight() { 507e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight(); 508e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 509e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 510e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 51106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette public void getOutline(@NonNull Outline outline) { 51206cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette mAnimatedVectorState.mVectorDrawable.getOutline(outline); 51306cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette } 51406cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette 51587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette /** @hide */ 51687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette @Override 51787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette public Insets getOpticalInsets() { 51887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette return mAnimatedVectorState.mVectorDrawable.getOpticalInsets(); 51987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette } 52087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette 52106cd7dce24876b54870f9ef3831237f8298773a9Alan Viverette @Override 522e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme) 523e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui throws XmlPullParserException, IOException { 524d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final AnimatedVectorDrawableState state = mAnimatedVectorState; 525e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 526e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui int eventType = parser.getEventType(); 527fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float pathErrorScale = 1; 5281f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu final int innerDepth = parser.getDepth() + 1; 5291f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu 5301f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu // Parse everything until the end of the animated-vector element. 5311f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu while (eventType != XmlPullParser.END_DOCUMENT 5321f859716a8e4b8c12d69ca8b3db8344de577d5c7Doris Liu && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) { 533e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (eventType == XmlPullParser.START_TAG) { 534e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui final String tagName = parser.getName(); 535e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (ANIMATED_VECTOR.equals(tagName)) { 536e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui final TypedArray a = obtainAttributes(res, theme, attrs, 537e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui R.styleable.AnimatedVectorDrawable); 538e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui int drawableRes = a.getResourceId( 539e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui R.styleable.AnimatedVectorDrawable_drawable, 0); 540e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (drawableRes != 0) { 541fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount VectorDrawable vectorDrawable = (VectorDrawable) res.getDrawable( 54255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui drawableRes, theme).mutate(); 543fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount vectorDrawable.setAllowCaching(false); 54417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette vectorDrawable.setCallback(mCallback); 545fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount pathErrorScale = vectorDrawable.getPixelSize(); 546d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (state.mVectorDrawable != null) { 547d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette state.mVectorDrawable.setCallback(null); 54817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 549d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette state.mVectorDrawable = vectorDrawable; 550e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 551e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui a.recycle(); 552e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } else if (TARGET.equals(tagName)) { 553e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui final TypedArray a = obtainAttributes(res, theme, attrs, 554e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui R.styleable.AnimatedVectorDrawableTarget); 555e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui final String target = a.getString( 556e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui R.styleable.AnimatedVectorDrawableTarget_name); 557d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final int animResId = a.getResourceId( 558e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui R.styleable.AnimatedVectorDrawableTarget_animation, 0); 559d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (animResId != 0) { 560d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (theme != null) { 561792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu // The animator here could be ObjectAnimator or AnimatorSet. 562792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu final Animator animator = AnimatorInflater.loadAnimator( 563d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette res, theme, animResId, pathErrorScale); 564a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu updateAnimatorProperty(animator, target, state.mVectorDrawable, 565a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu state.mShouldIgnoreInvalidAnim); 566792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu state.addTargetAnimator(target, animator); 567d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } else { 568d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // The animation may be theme-dependent. As a 569d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // workaround until Animator has full support for 570d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // applyTheme(), postpone loading the animator 571d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // until we have a theme in applyTheme(). 572d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette state.addPendingAnimator(animResId, pathErrorScale, target); 573d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 574d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 575e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 576e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui a.recycle(); 577e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 578e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 579e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 580e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui eventType = parser.next(); 581e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 5821588f0ff54b88240b55eeaba97e67f0f1dee5f92ztenghui 583d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // If we don't have any pending animations, we don't need to hold a 584d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // reference to the resources. 585d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mRes = state.mPendingAnims == null ? null : res; 586e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 587e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 588792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu private static void updateAnimatorProperty(Animator animator, String targetName, 589a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu VectorDrawable vectorDrawable, boolean ignoreInvalidAnim) { 590792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu if (animator instanceof ObjectAnimator) { 591792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu // Change the property of the Animator from using reflection based on the property 592792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu // name to a Property object that wraps the setter and getter for modifying that 593792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu // specific property for a given object. By replacing the reflection with a direct call, 594792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu // we can largely reduce the time it takes for a animator to modify a VD property. 595792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu PropertyValuesHolder[] holders = ((ObjectAnimator) animator).getValues(); 596792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu for (int i = 0; i < holders.length; i++) { 597792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu PropertyValuesHolder pvh = holders[i]; 598792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu String propertyName = pvh.getPropertyName(); 599792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu Object targetNameObj = vectorDrawable.getTargetByName(targetName); 600792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu Property property = null; 601792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu if (targetNameObj instanceof VectorDrawable.VObject) { 602792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu property = ((VectorDrawable.VObject) targetNameObj).getProperty(propertyName); 603792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } else if (targetNameObj instanceof VectorDrawable.VectorDrawableState) { 604792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu property = ((VectorDrawable.VectorDrawableState) targetNameObj) 605792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu .getProperty(propertyName); 606792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 607792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu if (property != null) { 608a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu if (containsSameValueType(pvh, property)) { 609a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu pvh.setProperty(property); 610a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } else if (!ignoreInvalidAnim) { 611a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu throw new RuntimeException("Wrong valueType for Property: " + propertyName 612a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu + ". Expected type: " + property.getType().toString() + ". Actual " 613a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu + "type defined in resources: " + pvh.getValueType().toString()); 614a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu 615a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } 616792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 617792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 618792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } else if (animator instanceof AnimatorSet) { 619792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu for (Animator anim : ((AnimatorSet) animator).getChildAnimations()) { 620a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu updateAnimatorProperty(anim, targetName, vectorDrawable, ignoreInvalidAnim); 621792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 622792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 623792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu } 624792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu 625a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu private static boolean containsSameValueType(PropertyValuesHolder holder, Property property) { 626a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu Class type1 = holder.getValueType(); 627a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu Class type2 = property.getType(); 628a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu if (type1 == float.class || type1 == Float.class) { 629a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu return type2 == float.class || type2 == Float.class; 630a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } else if (type1 == int.class || type1 == Integer.class) { 631a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu return type2 == int.class || type2 == Integer.class; 632a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } else { 633a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu return type1 == type2; 634a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } 635a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } 636a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu 63728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu /** 63828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu * Force to animate on UI thread. 63928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu * @hide 64028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu */ 64128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void forceAnimationOnUI() { 64228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu if (mAnimatorSet instanceof VectorDrawableAnimatorRT) { 64328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu VectorDrawableAnimatorRT animator = (VectorDrawableAnimatorRT) mAnimatorSet; 64428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu if (animator.isRunning()) { 64528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu throw new UnsupportedOperationException("Cannot force Animated Vector Drawable to" + 64628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu " run on UI thread when the animation has started on RenderThread."); 64728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 648853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu fallbackOntoUI(); 649853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu } 650853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu } 651853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu 652853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu private void fallbackOntoUI() { 653853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu if (mAnimatorSet instanceof VectorDrawableAnimatorRT) { 654853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu VectorDrawableAnimatorRT oldAnim = (VectorDrawableAnimatorRT) mAnimatorSet; 65528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSet = new VectorDrawableAnimatorUI(this); 65628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu if (mAnimatorSetFromXml != null) { 65728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSet.init(mAnimatorSetFromXml); 65828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 659853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu // Transfer the listener from RT animator to UI animator 660853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu if (oldAnim.mListener != null) { 661853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu mAnimatorSet.setListener(oldAnim.mListener); 662853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu } 663853b23d1fa625436b30dfab9b6cb7293c6c328b9Doris Liu oldAnim.transferPendingActions(mAnimatorSet); 66428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 66528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 66628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 667e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 668e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public boolean canApplyTheme() { 669d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme()) 670d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette || super.canApplyTheme(); 671e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 672e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 673e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 674e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void applyTheme(Theme t) { 675e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui super.applyTheme(t); 676e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 677e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui final VectorDrawable vectorDrawable = mAnimatedVectorState.mVectorDrawable; 678e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (vectorDrawable != null && vectorDrawable.canApplyTheme()) { 679e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui vectorDrawable.applyTheme(t); 680e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 681d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 682d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (t != null) { 683d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimatedVectorState.inflatePendingAnimators(t.getResources(), t); 684d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 685d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 686d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // If we don't have any pending animations, we don't need to hold a 687d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // reference to the resources. 688d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (mAnimatedVectorState.mPendingAnims == null) { 689d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mRes = null; 690d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 691e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 692e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 693e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui private static class AnimatedVectorDrawableState extends ConstantState { 694ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette @Config int mChangingConfigurations; 695e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui VectorDrawable mVectorDrawable; 696d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 697a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu private final boolean mShouldIgnoreInvalidAnim; 698a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu 699d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** Animators that require a theme before inflation. */ 700d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette ArrayList<PendingAnimator> mPendingAnims; 701d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 702d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** Fully inflated animators awaiting cloning into an AnimatorSet. */ 703d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette ArrayList<Animator> mAnimators; 704d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 705d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** Map of animators to their target object names */ 7066f6578e81c1df207da47e2e1337382341f271206Chet Haase ArrayMap<Animator, String> mTargetNameMap; 707e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 70817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy, 70917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette Callback owner, Resources res) { 710a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu mShouldIgnoreInvalidAnim = shouldIgnoreInvalidAnimation(); 711e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (copy != null) { 712e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mChangingConfigurations = copy.mChangingConfigurations; 713d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 7146f6578e81c1df207da47e2e1337382341f271206Chet Haase if (copy.mVectorDrawable != null) { 71517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette final ConstantState cs = copy.mVectorDrawable.getConstantState(); 71617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette if (res != null) { 71717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable = (VectorDrawable) cs.newDrawable(res); 71817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } else { 71917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable = (VectorDrawable) cs.newDrawable(); 72017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 72117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable = (VectorDrawable) mVectorDrawable.mutate(); 72217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable.setCallback(owner); 72317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable.setLayoutDirection(copy.mVectorDrawable.getLayoutDirection()); 7246f6578e81c1df207da47e2e1337382341f271206Chet Haase mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds()); 72517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mVectorDrawable.setAllowCaching(false); 7266f6578e81c1df207da47e2e1337382341f271206Chet Haase } 727d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 728d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (copy.mAnimators != null) { 729d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimators = new ArrayList<>(copy.mAnimators); 730d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 731d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 732d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (copy.mTargetNameMap != null) { 733d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mTargetNameMap = new ArrayMap<>(copy.mTargetNameMap); 734d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 735d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 736d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (copy.mPendingAnims != null) { 737d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mPendingAnims = new ArrayList<>(copy.mPendingAnims); 7386f6578e81c1df207da47e2e1337382341f271206Chet Haase } 73998916d146afe2ff25a439603f7d9559e74a790caztenghui } else { 74098916d146afe2ff25a439603f7d9559e74a790caztenghui mVectorDrawable = new VectorDrawable(); 741e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 742e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 743e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 744e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 745d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette public boolean canApplyTheme() { 746d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return (mVectorDrawable != null && mVectorDrawable.canApplyTheme()) 747d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette || mPendingAnims != null || super.canApplyTheme(); 748d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette } 749d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette 750d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette @Override 751e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public Drawable newDrawable() { 75217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette return new AnimatedVectorDrawable(this, null); 753e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 754e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 755e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 756e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public Drawable newDrawable(Resources res) { 75717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette return new AnimatedVectorDrawable(this, res); 758e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 759e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 760e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 761ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette public @Config int getChangingConfigurations() { 762e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mChangingConfigurations; 763e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 764e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 765d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public void addPendingAnimator(int resId, float pathErrorScale, String target) { 766d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (mPendingAnims == null) { 767d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mPendingAnims = new ArrayList<>(1); 768d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 769d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mPendingAnims.add(new PendingAnimator(resId, pathErrorScale, target)); 770d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 771d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 772d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public void addTargetAnimator(String targetName, Animator animator) { 773d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (mAnimators == null) { 774d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimators = new ArrayList<>(1); 775d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mTargetNameMap = new ArrayMap<>(1); 776d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 777d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimators.add(animator); 778d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mTargetNameMap.put(animator, targetName); 779d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 780d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (DBG_ANIMATION_VECTOR_DRAWABLE) { 781d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette Log.v(LOGTAG, "add animator for target " + targetName + " " + animator); 782d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 7836f6578e81c1df207da47e2e1337382341f271206Chet Haase } 784d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 785d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** 786d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * Prepares a local set of mutable animators based on the constant 787d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * state. 788d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * <p> 789d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * If there are any pending uninflated animators, attempts to inflate 790d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * them immediately against the provided resources object. 791d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * 792d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * @param animatorSet the animator set to which the animators should 793d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * be added 794d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * @param res the resources against which to inflate any pending 795d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * animators, or {@code null} if not available 796d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette */ 797d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public void prepareLocalAnimators(@NonNull AnimatorSet animatorSet, 798d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette @Nullable Resources res) { 799d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // Check for uninflated animators. We can remove this after we add 800d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // support for Animator.applyTheme(). See comments in inflate(). 801d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (mPendingAnims != null) { 802d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // Attempt to load animators without applying a theme. 803d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (res != null) { 804d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette inflatePendingAnimators(res, null); 805d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } else { 806d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette Log.e(LOGTAG, "Failed to load animators. Either the AnimatedVectorDrawable" 807d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette + " must be created using a Resources object or applyTheme() must be" 808d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette + " called with a non-null Theme object."); 809d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 810d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 811d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mPendingAnims = null; 812d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 813d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 814d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // Perform a deep copy of the constant state's animators. 815d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final int count = mAnimators == null ? 0 : mAnimators.size(); 816d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (count > 0) { 817d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final Animator firstAnim = prepareLocalAnimator(0); 818d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final AnimatorSet.Builder builder = animatorSet.play(firstAnim); 819d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette for (int i = 1; i < count; ++i) { 820d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final Animator nextAnim = prepareLocalAnimator(i); 821d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette builder.with(nextAnim); 822d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 823d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 824d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 825d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 826d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** 827d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * Prepares a local animator for the given index within the constant 828d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * state's list of animators. 829d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * 830d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * @param index the index of the animator within the constant state 831d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette */ 832d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette private Animator prepareLocalAnimator(int index) { 833d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final Animator animator = mAnimators.get(index); 834d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final Animator localAnimator = animator.clone(); 835d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final String targetName = mTargetNameMap.get(animator); 836d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final Object target = mVectorDrawable.getTargetByName(targetName); 83703f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu if (!mShouldIgnoreInvalidAnim) { 83803f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu if (target == null) { 83903f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu throw new IllegalStateException("Target with the name \"" + targetName 84003f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu + "\" cannot be found in the VectorDrawable to be animated."); 84103f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu } else if (!(target instanceof VectorDrawable.VectorDrawableState) 84203f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu && !(target instanceof VectorDrawable.VObject)) { 84303f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu throw new UnsupportedOperationException("Target should be either VGroup, VPath," 84403f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu + " or ConstantState, " + target.getClass() + " is not supported"); 84503f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu } 84603f2fcbd88478636acc9d67b9698b50e5b3eae25Doris Liu } 847d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette localAnimator.setTarget(target); 848d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette return localAnimator; 849d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 850d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 851d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** 852d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * Inflates pending animators, if any, against a theme. Clears the list of 853d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * pending animators. 854d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * 855d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * @param t the theme against which to inflate the animators 856d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette */ 857d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public void inflatePendingAnimators(@NonNull Resources res, @Nullable Theme t) { 858d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final ArrayList<PendingAnimator> pendingAnims = mPendingAnims; 859d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette if (pendingAnims != null) { 860d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mPendingAnims = null; 861d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 862d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette for (int i = 0, count = pendingAnims.size(); i < count; i++) { 863d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette final PendingAnimator pendingAnimator = pendingAnims.get(i); 864792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu final Animator animator = pendingAnimator.newInstance(res, t); 865a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu updateAnimatorProperty(animator, pendingAnimator.target, mVectorDrawable, 866a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu mShouldIgnoreInvalidAnim); 867792926a58c94563cf35d532cd3db888cc1cbeb7dDoris Liu addTargetAnimator(pendingAnimator.target, animator); 868d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 869d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 870d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 871d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 872d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette /** 873d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * Basically a constant state for Animators until we actually implement 874d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette * constant states for Animators. 875d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette */ 876d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette private static class PendingAnimator { 877d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public final int animResId; 878d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public final float pathErrorScale; 879d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public final String target; 880d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 881d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public PendingAnimator(int animResId, float pathErrorScale, String target) { 882d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette this.animResId = animResId; 883d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette this.pathErrorScale = pathErrorScale; 884d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette this.target = target; 885d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 886d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 887d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette public Animator newInstance(Resources res, Theme theme) { 888d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette return AnimatorInflater.loadAnimator(res, theme, animResId, pathErrorScale); 889d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 890e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 891e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 892e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 893e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 894e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public boolean isRunning() { 895d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette return mAnimatorSet.isRunning(); 896e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 897e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 89896052718067e1645afd7c7ae93bab536711349acztenghui /** 89996052718067e1645afd7c7ae93bab536711349acztenghui * Resets the AnimatedVectorDrawable to the start state as specified in the animators. 90096052718067e1645afd7c7ae93bab536711349acztenghui */ 90196052718067e1645afd7c7ae93bab536711349acztenghui public void reset() { 90228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu ensureAnimatorSet(); 90344027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 90444027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.w(LOGTAG, "calling reset on AVD: " + 90544027214d4f2154ebc9265912933bac282be3bb4Doris Liu ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState) 90644027214d4f2154ebc9265912933bac282be3bb4Doris Liu getConstantState()).mVectorDrawable.getConstantState()).mRootName 90744027214d4f2154ebc9265912933bac282be3bb4Doris Liu + ", at: " + this); 90844027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 909766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mAnimatorSet.reset(); 91096052718067e1645afd7c7ae93bab536711349acztenghui } 91196052718067e1645afd7c7ae93bab536711349acztenghui 912e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 913e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void start() { 914d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette ensureAnimatorSet(); 91544027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 91644027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.w(LOGTAG, "calling start on AVD: " + 91744027214d4f2154ebc9265912933bac282be3bb4Doris Liu ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState) 91844027214d4f2154ebc9265912933bac282be3bb4Doris Liu getConstantState()).mVectorDrawable.getConstantState()).mRootName 91944027214d4f2154ebc9265912933bac282be3bb4Doris Liu + ", at: " + this); 92044027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 921d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimatorSet.start(); 922e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 923e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 924d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette @NonNull 925d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette private void ensureAnimatorSet() { 92628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu if (mAnimatorSetFromXml == null) { 927766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly 928766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // with a list of LocalAnimators. 92928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSetFromXml = new AnimatorSet(); 93028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatedVectorState.prepareLocalAnimators(mAnimatorSetFromXml, mRes); 93128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSet.init(mAnimatorSetFromXml); 932d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mRes = null; 933d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 934d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette } 935d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 936e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 937e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void stop() { 93844027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 93944027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.w(LOGTAG, "calling stop on AVD: " + 94044027214d4f2154ebc9265912933bac282be3bb4Doris Liu ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState) 94144027214d4f2154ebc9265912933bac282be3bb4Doris Liu getConstantState()).mVectorDrawable.getConstantState()) 94244027214d4f2154ebc9265912933bac282be3bb4Doris Liu .mRootName + ", at: " + this); 94344027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 944d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimatorSet.end(); 945e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 9466e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette 9476e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette /** 9486e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette * Reverses ongoing animations or starts pending animations in reverse. 9496e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette * <p> 9505b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui * NOTE: Only works if all animations support reverse. Otherwise, this will 9515b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui * do nothing. 9527bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui * @hide 9536e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette */ 9547bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui public void reverse() { 955d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette ensureAnimatorSet(); 956d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 957d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette // Only reverse when all the animators can be reversed. 9585b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui if (!canReverse()) { 9595b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()"); 9605b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui return; 9615b84eace6cb79c42fe43480f08c68b7dea4e074aztenghui } 962d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette 963d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette mAnimatorSet.reverse(); 9646e0a9fa6ed86e918bfed5310d2522b2c2a527ef0Alan Viverette } 9657bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui 9667bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui /** 9677bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui * @hide 9687bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui */ 9697bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui public boolean canReverse() { 970d8d9a75f6a111b962bf5260a4dca87398405d95bAlan Viverette return mAnimatorSet.canReverse(); 9717bc6a3f023ca3e1dde91fc97b6036dee3ba538a2ztenghui } 97217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 97317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette private final Callback mCallback = new Callback() { 97417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette @Override 975f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette public void invalidateDrawable(@NonNull Drawable who) { 97617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette invalidateSelf(); 97717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 97817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 97917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette @Override 980f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { 98117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette scheduleSelf(what, when); 98217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 98317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette 98417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette @Override 985f6d87ec193f17e8dad82c9994ba7a58e975d364bAlan Viverette public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { 98617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette unscheduleSelf(what); 98717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 98817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette }; 98983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 99083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui @Override 99183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui public void registerAnimationCallback(@NonNull AnimationCallback callback) { 99283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (callback == null) { 99383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui return; 99483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 99583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 99683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // Add listener accordingly. 99783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimationCallbacks == null) { 99883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui mAnimationCallbacks = new ArrayList<>(); 99983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 100083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 100183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui mAnimationCallbacks.add(callback); 100283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 100383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimatorListener == null) { 100483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // Create a animator listener and trigger the callback events when listener is 100583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // triggered. 100683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui mAnimatorListener = new AnimatorListenerAdapter() { 100783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui @Override 100883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui public void onAnimationStart(Animator animation) { 100983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui ArrayList<AnimationCallback> tmpCallbacks = new ArrayList<>(mAnimationCallbacks); 101083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui int size = tmpCallbacks.size(); 101183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui for (int i = 0; i < size; i ++) { 101283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui tmpCallbacks.get(i).onAnimationStart(AnimatedVectorDrawable.this); 101383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 101483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 101583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 101683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui @Override 101783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui public void onAnimationEnd(Animator animation) { 101883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui ArrayList<AnimationCallback> tmpCallbacks = new ArrayList<>(mAnimationCallbacks); 101983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui int size = tmpCallbacks.size(); 102083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui for (int i = 0; i < size; i ++) { 102183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui tmpCallbacks.get(i).onAnimationEnd(AnimatedVectorDrawable.this); 102283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 102383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 102483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui }; 102583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 1026766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mAnimatorSet.setListener(mAnimatorListener); 102783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 102883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 102983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // A helper function to clean up the animator listener in the mAnimatorSet. 103083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui private void removeAnimatorSetListener() { 103183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimatorListener != null) { 103228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mAnimatorSet.removeListener(mAnimatorListener); 103383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui mAnimatorListener = null; 103483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 103583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 103683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 103783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui @Override 103883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui public boolean unregisterAnimationCallback(@NonNull AnimationCallback callback) { 103983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimationCallbacks == null || callback == null) { 104083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // Nothing to be removed. 104183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui return false; 104283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 104383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui boolean removed = mAnimationCallbacks.remove(callback); 104483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 104583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui // When the last call back unregistered, remove the listener accordingly. 104683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimationCallbacks.size() == 0) { 104783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui removeAnimatorSetListener(); 104883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 104983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui return removed; 105083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 105183a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 105283a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui @Override 105383a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui public void clearAnimationCallbacks() { 105483a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui removeAnimatorSetListener(); 105583a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui if (mAnimationCallbacks == null) { 105683a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui return; 105783a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 105883a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui 105983a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui mAnimationCallbacks.clear(); 106083a52031fd5c277d0c6e75da50bf8013e8a70399ztenghui } 1061766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 106228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private interface VectorDrawableAnimator { 1063988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu void init(@NonNull AnimatorSet set); 106428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void start(); 106528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void end(); 106628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void reset(); 106728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void reverse(); 106828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu boolean canReverse(); 106928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void setListener(AnimatorListener listener); 107028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void removeListener(AnimatorListener listener); 107128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu void onDraw(Canvas canvas); 107228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu boolean isStarted(); 107328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu boolean isRunning(); 1074d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu boolean isInfinite(); 1075d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu void pause(); 1076d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu void resume(); 107728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 107828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 107928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator { 1080988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // mSet is only initialized in init(). So we need to check whether it is null before any 1081988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // operation. 1082988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu private AnimatorSet mSet = null; 108328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private final Drawable mDrawable; 1084988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // Caching the listener in the case when listener operation is called before the mSet is 1085988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // setup by init(). 1086988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu private ArrayList<AnimatorListener> mListenerArray = null; 1087d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu private boolean mIsInfinite = false; 108828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 1089988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu VectorDrawableAnimatorUI(@NonNull AnimatedVectorDrawable drawable) { 109028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mDrawable = drawable; 109128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 109228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 109328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 1094988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu public void init(@NonNull AnimatorSet set) { 1095988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet != null) { 1096988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // Already initialized 1097988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " + 1098988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu "re-initialized"); 1099988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 1100988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // Keep a deep copy of the set, such that set can be still be constantly representing 1101988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // the static content from XML file. 1102988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mSet = set.clone(); 1103d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mIsInfinite = mSet.getTotalDuration() == Animator.DURATION_INFINITE; 1104988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu 1105988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // If there are listeners added before calling init(), now they should be setup. 1106988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mListenerArray != null && !mListenerArray.isEmpty()) { 1107988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu for (int i = 0; i < mListenerArray.size(); i++) { 1108988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mSet.addListener(mListenerArray.get(i)); 1109988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 1110988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mListenerArray.clear(); 1111988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mListenerArray = null; 1112988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 111328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 111428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 1115988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // Although start(), reset() and reverse() should call init() already, it is better to 1116988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu // protect these functions from NPE in any situation. 111728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 111828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void start() { 1119988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null || mSet.isStarted()) { 112028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu return; 112128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 112228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mSet.start(); 112328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu invalidateOwningView(); 112428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 112528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 112628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 112728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void end() { 1128988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null) { 1129988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return; 1130988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 113128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mSet.end(); 113228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 113328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 113428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 113528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void reset() { 1136988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null) { 1137988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return; 1138988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 113928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu start(); 114028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mSet.cancel(); 114128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 114228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 114328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 114428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void reverse() { 1145988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null) { 1146988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return; 1147988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 114828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mSet.reverse(); 114928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu invalidateOwningView(); 115028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 115128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 115228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 115328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean canReverse() { 1154988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return mSet != null && mSet.canReverse(); 115528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 115628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 115728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 115828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void setListener(AnimatorListener listener) { 1159988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null) { 1160988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mListenerArray == null) { 1161988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mListenerArray = new ArrayList<AnimatorListener>(); 1162988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 1163988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mListenerArray.add(listener); 1164988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } else { 1165988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mSet.addListener(listener); 1166988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 116728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 116828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 116928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 117028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void removeListener(AnimatorListener listener) { 1171988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet == null) { 1172988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mListenerArray == null) { 1173988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return; 1174988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 1175988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mListenerArray.remove(listener); 1176988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } else { 1177988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu mSet.removeListener(listener); 1178988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu } 117928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 118028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 118128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 118228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void onDraw(Canvas canvas) { 1183988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu if (mSet != null && mSet.isStarted()) { 118428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu invalidateOwningView(); 118528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 118628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 118728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 118828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 118928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean isStarted() { 1190988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return mSet != null && mSet.isStarted(); 119128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 119228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 119328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 119428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean isRunning() { 1195988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu return mSet != null && mSet.isRunning(); 119628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 119728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 1198d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1199d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public boolean isInfinite() { 1200d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu return mIsInfinite; 1201d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1202d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 1203d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1204d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public void pause() { 1205d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu if (mSet == null) { 1206d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu return; 1207d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1208d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mSet.pause(); 1209d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1210d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 1211d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1212d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public void resume() { 1213d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu if (mSet == null) { 1214d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu return; 1215d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1216d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mSet.resume(); 1217d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1218d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 121928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private void invalidateOwningView() { 122028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu mDrawable.invalidateSelf(); 122128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 122228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 122328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 1224766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu /** 1225766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * @hide 1226766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu */ 122728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator { 1228c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu private static final int START_ANIMATION = 1; 1229c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu private static final int REVERSE_ANIMATION = 2; 123044027214d4f2154ebc9265912933bac282be3bb4Doris Liu private static final int RESET_ANIMATION = 3; 123144027214d4f2154ebc9265912933bac282be3bb4Doris Liu private static final int END_ANIMATION = 4; 1232c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu 1233c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu // If the duration of an animation is more than 300 frames, we cap the sample size to 300. 1234c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu private static final int MAX_SAMPLE_POINTS = 300; 1235766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private AnimatorListener mListener = null; 1236766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private final LongArray mStartDelays = new LongArray(); 1237766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private PropertyValuesHolder.PropertyValues mTmpValues = 1238766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu new PropertyValuesHolder.PropertyValues(); 1239766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private long mSetPtr = 0; 1240766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private boolean mContainsSequentialAnimators = false; 1241766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private boolean mStarted = false; 1242766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private boolean mInitialized = false; 1243766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private boolean mIsReversible = false; 1244d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu private boolean mIsInfinite = false; 1245766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: Consider using NativeAllocationRegistery to track native allocation 1246766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private final VirtualRefBasePtr mSetRefBasePtr; 1247766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private WeakReference<RenderNode> mLastSeenTarget = null; 1248c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu private int mLastListenerId = 0; 124944027214d4f2154ebc9265912933bac282be3bb4Doris Liu private final IntArray mPendingAnimationActions = new IntArray(); 1250718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu private final AnimatedVectorDrawable mDrawable; 1251766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 125228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) { 1253c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu mDrawable = drawable; 1254766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mSetPtr = nCreateAnimatorSet(); 1255766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Increment ref count on native AnimatorSet, so it doesn't get released before Java 1256766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // side is done using it. 1257766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr); 1258766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1259766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 126028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 1261988fc6fa43d4f35d17b4ab7574863f5017fd289aTeng-Hui Zhu public void init(@NonNull AnimatorSet set) { 1262766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mInitialized) { 1263766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Already initialized 1264766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " + 1265766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu "re-initialized"); 1266766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1267766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu parseAnimatorSet(set, 0); 1268718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu long vectorDrawableTreePtr = mDrawable.mAnimatedVectorState.mVectorDrawable 1269718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu .getNativeTree(); 1270718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu nSetVectorDrawableTarget(mSetPtr, vectorDrawableTreePtr); 1271766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mInitialized = true; 1272d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu mIsInfinite = set.getTotalDuration() == Animator.DURATION_INFINITE; 1273766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1274766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Check reversible. 1275c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu mIsReversible = true; 1276766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mContainsSequentialAnimators) { 1277766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mIsReversible = false; 1278766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else { 1279766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Check if there's any start delay set on child 1280766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu for (int i = 0; i < mStartDelays.size(); i++) { 1281766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mStartDelays.get(i) > 0) { 1282766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mIsReversible = false; 1283766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return; 1284766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1285766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1286766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1287766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1288766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1289766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void parseAnimatorSet(AnimatorSet set, long startTime) { 1290766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu ArrayList<Animator> animators = set.getChildAnimations(); 1291766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1292766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu boolean playTogether = set.shouldPlayTogether(); 129328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu // Convert AnimatorSet to VectorDrawableAnimatorRT 1294766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu for (int i = 0; i < animators.size(); i++) { 1295766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu Animator animator = animators.get(i); 1296766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Here we only support ObjectAnimator 1297766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (animator instanceof AnimatorSet) { 1298766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu parseAnimatorSet((AnimatorSet) animator, startTime); 1299766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else if (animator instanceof ObjectAnimator) { 1300766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createRTAnimator((ObjectAnimator) animator, startTime); 1301766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } // ignore ValueAnimators and others because they don't directly modify VD 1302766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // therefore will be useless to AVD. 1303766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1304766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (!playTogether) { 1305766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Assume not play together means play sequentially 1306766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu startTime += animator.getTotalDuration(); 1307766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mContainsSequentialAnimators = true; 1308766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1309766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1310766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1311766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1312766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: This method reads animation data from already parsed Animators. We need to move 1313766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // this step further up the chain in the parser to avoid the detour. 1314766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createRTAnimator(ObjectAnimator animator, long startTime) { 1315766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu PropertyValuesHolder[] values = animator.getValues(); 1316766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu Object target = animator.getTarget(); 1317766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (target instanceof VectorDrawable.VGroup) { 1318766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createRTAnimatorForGroup(values, animator, (VectorDrawable.VGroup) target, 1319766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu startTime); 1320766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else if (target instanceof VectorDrawable.VPath) { 1321766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu for (int i = 0; i < values.length; i++) { 1322766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values[i].getPropertyValues(mTmpValues); 1323766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mTmpValues.endValue instanceof PathParser.PathData && 1324766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mTmpValues.propertyName.equals("pathData")) { 1325766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createRTAnimatorForPath(animator, (VectorDrawable.VPath) target, 1326766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu startTime); 1327766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else if (target instanceof VectorDrawable.VFullPath) { 1328766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target, 1329766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu startTime); 1330a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { 1331766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu throw new IllegalArgumentException("ClipPath only supports PathData " + 1332766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu "property"); 1333766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1334766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1335766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else if (target instanceof VectorDrawable.VectorDrawableState) { 1336766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createRTAnimatorForRootGroup(values, animator, 1337766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu (VectorDrawable.VectorDrawableState) target, startTime); 1338766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1339766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1340766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1341766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createRTAnimatorForGroup(PropertyValuesHolder[] values, 1342766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu ObjectAnimator animator, VectorDrawable.VGroup target, 1343766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long startTime) { 1344766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1345766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long nativePtr = target.getNativePtr(); 1346766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu int propertyId; 1347766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu for (int i = 0; i < values.length; i++) { 1348766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: We need to support the rare case in AVD where no start value is provided 1349766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values[i].getPropertyValues(mTmpValues); 1350766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu propertyId = VectorDrawable.VGroup.getPropertyIndex(mTmpValues.propertyName); 1351766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mTmpValues.type != Float.class && mTmpValues.type != float.class) { 1352766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 1353766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu Log.e(LOGTAG, "Unsupported type: " + 1354766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mTmpValues.type + ". Only float value is supported for Groups."); 1355766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1356766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu continue; 1357766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1358766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (propertyId < 0) { 1359766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 1360766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu Log.e(LOGTAG, "Unsupported property: " + 1361766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mTmpValues.propertyName + " for Vector Drawable Group"); 1362766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1363766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu continue; 1364766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1365766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId, 1366766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); 1367766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mTmpValues.dataSource != null) { 1368c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, 1369c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu animator.getDuration()); 1370766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); 1371766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1372766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createNativeChildAnimator(propertyPtr, startTime, animator); 1373766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1374766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1375766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createRTAnimatorForPath( ObjectAnimator animator, VectorDrawable.VPath target, 1376766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long startTime) { 1377766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1378766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long nativePtr = target.getNativePtr(); 1379766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long startPathDataPtr = ((PathParser.PathData) mTmpValues.startValue) 1380766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu .getNativePtr(); 1381766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long endPathDataPtr = ((PathParser.PathData) mTmpValues.endValue) 1382766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu .getNativePtr(); 1383766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long propertyPtr = nCreatePathDataPropertyHolder(nativePtr, startPathDataPtr, 1384766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu endPathDataPtr); 1385766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createNativeChildAnimator(propertyPtr, startTime, animator); 1386766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1387766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1388766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createRTAnimatorForFullPath(ObjectAnimator animator, 1389766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu VectorDrawable.VFullPath target, long startTime) { 1390766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1391766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu int propertyId = target.getPropertyIndex(mTmpValues.propertyName); 1392766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long propertyPtr; 1393766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long nativePtr = target.getNativePtr(); 1394766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mTmpValues.type == Float.class || mTmpValues.type == float.class) { 1395766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (propertyId < 0) { 1396a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { 1397ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu return; 1398ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } else { 1399ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu throw new IllegalArgumentException("Property: " + mTmpValues.propertyName 1400ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu + " is not supported for FullPath"); 1401ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } 1402766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1403766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId, 1404766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); 1405c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mTmpValues.dataSource != null) { 1406c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu // Pass keyframe data to native, if any. 1407c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, 1408c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu animator.getDuration()); 1409c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); 1410c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1411766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1412766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) { 1413766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId, 1414766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue); 1415c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mTmpValues.dataSource != null) { 1416c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu // Pass keyframe data to native, if any. 1417c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int[] dataPoints = createIntDataPoints(mTmpValues.dataSource, 1418c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu animator.getDuration()); 1419c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); 1420c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1421766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } else { 1422a57e95a6a351242941e5cef97aaaa1fb34f20a9dDoris Liu if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { 1423ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu return; 1424ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } else { 1425ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu throw new UnsupportedOperationException("Unsupported type: " + 1426ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu mTmpValues.type + ". Only float, int or PathData value is " + 1427ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu "supported for Paths."); 1428ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu } 1429766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1430766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu createNativeChildAnimator(propertyPtr, startTime, animator); 1431766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1432766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1433766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values, 1434766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu ObjectAnimator animator, VectorDrawable.VectorDrawableState target, 1435766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long startTime) { 1436c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu long nativePtr = target.getNativeRenderer(); 1437c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (!animator.getPropertyName().equals("alpha")) { 1438c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { 1439c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu return; 1440c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } else { 1441c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu throw new UnsupportedOperationException("Only alpha is supported for root " 1442c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu + "group"); 1443766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1444c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1445c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu Float startValue = null; 1446c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu Float endValue = null; 1447c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu for (int i = 0; i < values.length; i++) { 1448c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu values[i].getPropertyValues(mTmpValues); 1449c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mTmpValues.propertyName.equals("alpha")) { 1450c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu startValue = (Float) mTmpValues.startValue; 1451c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu endValue = (Float) mTmpValues.endValue; 1452c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu break; 1453766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1454c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1455c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (startValue == null && endValue == null) { 1456c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) { 1457c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu return; 1458c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } else { 1459c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu throw new UnsupportedOperationException("No alpha values are specified"); 1460766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1461c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1462c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue); 1463c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (mTmpValues.dataSource != null) { 1464c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu // Pass keyframe data to native, if any. 1465c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource, 1466c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu animator.getDuration()); 1467c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); 1468c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1469c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu createNativeChildAnimator(propertyPtr, startTime, animator); 1470c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1471c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu 1472c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu /** 1473c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu * Calculate the amount of frames an animation will run based on duration. 1474c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu */ 1475c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu private static int getFrameCount(long duration) { 1476c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos(); 1477c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); 1478c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs); 1479c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu // We need 2 frames of data minimum. 1480c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu numAnimFrames = Math.max(2, numAnimFrames); 1481c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu if (numAnimFrames > MAX_SAMPLE_POINTS) { 1482c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu Log.w("AnimatedVectorDrawable", "Duration for the animation is too long :" + 1483c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu duration + ", the animation will subsample the keyframe or path data."); 1484c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu numAnimFrames = MAX_SAMPLE_POINTS; 1485c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1486c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu return numAnimFrames; 1487766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1488766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1489766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // These are the data points that define the value of the animating properties. 1490766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // e.g. translateX and translateY can animate along a Path, at any fraction in [0, 1] 1491766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // a point on the path corresponds to the values of translateX and translateY. 1492766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // TODO: (Optimization) We should pass the path down in native and chop it into segments 1493766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // in native. 1494c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu private static float[] createFloatDataPoints( 1495766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) { 1496c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int numAnimFrames = getFrameCount(duration); 1497766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float values[] = new float[numAnimFrames]; 1498766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float lastFrame = numAnimFrames - 1; 1499766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu for (int i = 0; i < numAnimFrames; i++) { 1500766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float fraction = i / lastFrame; 1501766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu values[i] = (Float) dataSource.getValueAtFraction(fraction); 1502766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1503766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return values; 1504766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1505766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1506c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu private static int[] createIntDataPoints( 1507c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) { 1508c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int numAnimFrames = getFrameCount(duration); 1509c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu int values[] = new int[numAnimFrames]; 1510c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu float lastFrame = numAnimFrames - 1; 1511c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu for (int i = 0; i < numAnimFrames; i++) { 1512c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu float fraction = i / lastFrame; 1513c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu values[i] = (Integer) dataSource.getValueAtFraction(fraction); 1514c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1515c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu return values; 1516c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu } 1517c9493879d7b38b9d0b5b09aa3760966a3ca33eacDoris Liu 1518766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private void createNativeChildAnimator(long propertyPtr, long extraDelay, 1519766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu ObjectAnimator animator) { 1520766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long duration = animator.getDuration(); 1521766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu int repeatCount = animator.getRepeatCount(); 1522766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long startDelay = extraDelay + animator.getStartDelay(); 1523766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu TimeInterpolator interpolator = animator.getInterpolator(); 1524766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long nativeInterpolator = 1525766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration); 1526766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1527766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu startDelay *= ValueAnimator.getDurationScale(); 1528766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu duration *= ValueAnimator.getDurationScale(); 1529766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1530766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mStartDelays.add(startDelay); 1531766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration, 1532f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu repeatCount, animator.getRepeatMode()); 1533766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1534766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1535766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu /** 1536766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * Holds a weak reference to the target that was last seen (through the DisplayListCanvas 1537766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * in the last draw call), so that when animator set needs to start, we can add the animator 1538766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu * to the last seen RenderNode target and start right away. 1539766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu */ 1540766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu protected void recordLastSeenTarget(DisplayListCanvas canvas) { 1541718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu final RenderNode node = RenderNodeAnimatorSetHelper.getTarget(canvas); 1542718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu mLastSeenTarget = new WeakReference<RenderNode>(node); 1543718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu // Add the animator to the list of animators on every draw 1544718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu if (mInitialized || mPendingAnimationActions.size() > 0) { 1545718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu if (useTarget(node)) { 1546718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 1547718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu Log.d(LOGTAG, "Target is set in the next frame"); 1548718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu } 1549718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu for (int i = 0; i < mPendingAnimationActions.size(); i++) { 1550718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu handlePendingAction(mPendingAnimationActions.get(i)); 1551718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu } 1552718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu mPendingAnimationActions.clear(); 1553c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 155444027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 155544027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 155644027214d4f2154ebc9265912933bac282be3bb4Doris Liu 155744027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void handlePendingAction(int pendingAnimationAction) { 155844027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (pendingAnimationAction == START_ANIMATION) { 155944027214d4f2154ebc9265912933bac282be3bb4Doris Liu startAnimation(); 156044027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else if (pendingAnimationAction == REVERSE_ANIMATION) { 156144027214d4f2154ebc9265912933bac282be3bb4Doris Liu reverseAnimation(); 156244027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else if (pendingAnimationAction == RESET_ANIMATION) { 156344027214d4f2154ebc9265912933bac282be3bb4Doris Liu resetAnimation(); 156444027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else if (pendingAnimationAction == END_ANIMATION) { 156544027214d4f2154ebc9265912933bac282be3bb4Doris Liu endAnimation(); 156644027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else { 156744027214d4f2154ebc9265912933bac282be3bb4Doris Liu throw new UnsupportedOperationException("Animation action " + 156844027214d4f2154ebc9265912933bac282be3bb4Doris Liu pendingAnimationAction + "is not supported"); 1569766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1570766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1571766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1572766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private boolean useLastSeenTarget() { 15738b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu if (mLastSeenTarget != null) { 15748b083206aef627b6445a8c6be8bf5bb1d778a7f8Doris Liu final RenderNode target = mLastSeenTarget.get(); 1575718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu return useTarget(target); 1576718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu } 1577718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu return false; 1578718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu } 1579718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu 1580718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu private boolean useTarget(RenderNode target) { 1581718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu if (target != null && target.isAttached()) { 1582718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu target.registerVectorDrawableAnimator(this); 1583718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu return true; 1584766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1585766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return false; 1586766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1587766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1588c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu private void invalidateOwningView() { 1589c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu mDrawable.invalidateSelf(); 1590c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu } 1591c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu 159244027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void addPendingAction(int pendingAnimationAction) { 159344027214d4f2154ebc9265912933bac282be3bb4Doris Liu invalidateOwningView(); 159444027214d4f2154ebc9265912933bac282be3bb4Doris Liu mPendingAnimationActions.add(pendingAnimationAction); 159544027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 159644027214d4f2154ebc9265912933bac282be3bb4Doris Liu 159728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 1598766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public void start() { 1599766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (!mInitialized) { 1600766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return; 1601766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1602766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 160344027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (useLastSeenTarget()) { 160444027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 160544027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java"); 160644027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 160744027214d4f2154ebc9265912933bac282be3bb4Doris Liu startAnimation(); 160844027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else { 160944027214d4f2154ebc9265912933bac282be3bb4Doris Liu addPendingAction(START_ANIMATION); 1610766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1611766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1612766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 161328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 1614766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public void end() { 161544027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (!mInitialized) { 161644027214d4f2154ebc9265912933bac282be3bb4Doris Liu return; 161744027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 161844027214d4f2154ebc9265912933bac282be3bb4Doris Liu 161944027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (useLastSeenTarget()) { 162044027214d4f2154ebc9265912933bac282be3bb4Doris Liu endAnimation(); 162144027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else { 162244027214d4f2154ebc9265912933bac282be3bb4Doris Liu addPendingAction(END_ANIMATION); 1623766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1624766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1625766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 162628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 1627c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu public void reset() { 162844027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (!mInitialized) { 162944027214d4f2154ebc9265912933bac282be3bb4Doris Liu return; 163044027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 163144027214d4f2154ebc9265912933bac282be3bb4Doris Liu 163244027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (useLastSeenTarget()) { 163344027214d4f2154ebc9265912933bac282be3bb4Doris Liu resetAnimation(); 163444027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else { 163544027214d4f2154ebc9265912933bac282be3bb4Doris Liu addPendingAction(RESET_ANIMATION); 1636766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1637766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1638766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1639766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential 1640766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // animators or when the animator set has a start delay 164128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 164228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void reverse() { 1643c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu if (!mIsReversible || !mInitialized) { 1644c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu return; 1645c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 164644027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (useLastSeenTarget()) { 164744027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 164844027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java"); 164944027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 165044027214d4f2154ebc9265912933bac282be3bb4Doris Liu reverseAnimation(); 165144027214d4f2154ebc9265912933bac282be3bb4Doris Liu } else { 165244027214d4f2154ebc9265912933bac282be3bb4Doris Liu addPendingAction(REVERSE_ANIMATION); 1653766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 165444027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 165544027214d4f2154ebc9265912933bac282be3bb4Doris Liu 165644027214d4f2154ebc9265912933bac282be3bb4Doris Liu // This should only be called after animator has been added to the RenderNode target. 165744027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void startAnimation() { 1658c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 165944027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.w(LOGTAG, "starting animation on VD: " + 166044027214d4f2154ebc9265912933bac282be3bb4Doris Liu ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState) 166144027214d4f2154ebc9265912933bac282be3bb4Doris Liu mDrawable.getConstantState()).mVectorDrawable.getConstantState()) 166244027214d4f2154ebc9265912933bac282be3bb4Doris Liu .mRootName); 1663c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 1664c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu mStarted = true; 166544027214d4f2154ebc9265912933bac282be3bb4Doris Liu nStart(mSetPtr, this, ++mLastListenerId); 166644027214d4f2154ebc9265912933bac282be3bb4Doris Liu invalidateOwningView(); 166744027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (mListener != null) { 166844027214d4f2154ebc9265912933bac282be3bb4Doris Liu mListener.onAnimationStart(null); 166944027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 167044027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 167144027214d4f2154ebc9265912933bac282be3bb4Doris Liu 167244027214d4f2154ebc9265912933bac282be3bb4Doris Liu // This should only be called after animator has been added to the RenderNode target. 167344027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void endAnimation() { 167444027214d4f2154ebc9265912933bac282be3bb4Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 167544027214d4f2154ebc9265912933bac282be3bb4Doris Liu Log.w(LOGTAG, "ending animation on VD: " + 167644027214d4f2154ebc9265912933bac282be3bb4Doris Liu ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState) 167744027214d4f2154ebc9265912933bac282be3bb4Doris Liu mDrawable.getConstantState()).mVectorDrawable.getConstantState()) 167844027214d4f2154ebc9265912933bac282be3bb4Doris Liu .mRootName); 167944027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 168044027214d4f2154ebc9265912933bac282be3bb4Doris Liu nEnd(mSetPtr); 168144027214d4f2154ebc9265912933bac282be3bb4Doris Liu invalidateOwningView(); 168244027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 168344027214d4f2154ebc9265912933bac282be3bb4Doris Liu 168444027214d4f2154ebc9265912933bac282be3bb4Doris Liu // This should only be called after animator has been added to the RenderNode target. 168544027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void resetAnimation() { 168644027214d4f2154ebc9265912933bac282be3bb4Doris Liu nReset(mSetPtr); 168744027214d4f2154ebc9265912933bac282be3bb4Doris Liu invalidateOwningView(); 168844027214d4f2154ebc9265912933bac282be3bb4Doris Liu } 168944027214d4f2154ebc9265912933bac282be3bb4Doris Liu 169044027214d4f2154ebc9265912933bac282be3bb4Doris Liu // This should only be called after animator has been added to the RenderNode target. 169144027214d4f2154ebc9265912933bac282be3bb4Doris Liu private void reverseAnimation() { 169244027214d4f2154ebc9265912933bac282be3bb4Doris Liu mStarted = true; 1693c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu nReverse(mSetPtr, this, ++mLastListenerId); 1694c21e8bcb013a6a562aa6288143368d9dba80fef4Doris Liu invalidateOwningView(); 1695c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu if (mListener != null) { 1696c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu mListener.onAnimationStart(null); 1697c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 1698766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1699766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1700766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu public long getAnimatorNativePtr() { 1701766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return mSetPtr; 1702766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1703766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 170428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 170528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean canReverse() { 1706766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return mIsReversible; 1707766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1708766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 170928cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 171028cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean isStarted() { 1711766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return mStarted; 1712766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1713766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 171428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 171528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public boolean isRunning() { 1716766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (!mInitialized) { 1717766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return false; 1718766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1719766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu return mStarted; 1720766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1721766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 172228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 172328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void setListener(AnimatorListener listener) { 1724766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mListener = listener; 1725766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1726766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 172728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 172828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void removeListener(AnimatorListener listener) { 1729766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mListener = null; 1730766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1731766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 173228cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu @Override 173328cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu public void onDraw(Canvas canvas) { 173428cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu if (canvas.isHardwareAccelerated()) { 173528cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu recordLastSeenTarget((DisplayListCanvas) canvas); 173628cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 173728cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu } 173828cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu 1739d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1740d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public boolean isInfinite() { 1741d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu return mIsInfinite; 1742d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1743d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 1744d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1745d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public void pause() { 1746d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu // TODO: Implement pause for Animator On RT. 1747d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1748d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 1749d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu @Override 1750d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu public void resume() { 1751d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu // TODO: Implement resume for Animator On RT. 1752d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu } 1753d049837397e72def57a71bf6f3387cdbf179fa19Doris Liu 1754c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu private void onAnimationEnd(int listenerId) { 1755c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu if (listenerId != mLastListenerId) { 1756c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu return; 1757c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 1758c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu if (DBG_ANIMATION_VECTOR_DRAWABLE) { 1759c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu Log.d(LOGTAG, "on finished called from native"); 1760c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu } 1761766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mStarted = false; 17621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu // Invalidate in the end of the animation to make sure the data in 17631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu // RT thread is synced back to UI thread. 17641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu invalidateOwningView(); 1765766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu if (mListener != null) { 1766766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu mListener.onAnimationEnd(null); 1767766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1768766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1769766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1770766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu // onFinished: should be called from native 177128cfd20f024a56a927014351c8bdf9d8552603e3Doris Liu private static void callOnFinished(VectorDrawableAnimatorRT set, int id) { 1772c4bb185d41cfb960ed9a3178a4f8974c351abdb0Doris Liu set.onAnimationEnd(id); 1773766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1774126df850ce6b5f8a355534eb09235e22995f0116Doris Liu 1775126df850ce6b5f8a355534eb09235e22995f0116Doris Liu private void transferPendingActions(VectorDrawableAnimator animatorSet) { 1776126df850ce6b5f8a355534eb09235e22995f0116Doris Liu for (int i = 0; i < mPendingAnimationActions.size(); i++) { 1777126df850ce6b5f8a355534eb09235e22995f0116Doris Liu int pendingAction = mPendingAnimationActions.get(i); 1778126df850ce6b5f8a355534eb09235e22995f0116Doris Liu if (pendingAction == START_ANIMATION) { 1779126df850ce6b5f8a355534eb09235e22995f0116Doris Liu animatorSet.start(); 1780126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } else if (pendingAction == END_ANIMATION) { 1781126df850ce6b5f8a355534eb09235e22995f0116Doris Liu animatorSet.end(); 1782126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } else if (pendingAction == REVERSE_ANIMATION) { 1783126df850ce6b5f8a355534eb09235e22995f0116Doris Liu animatorSet.reverse(); 1784126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } else if (pendingAction == RESET_ANIMATION) { 1785126df850ce6b5f8a355534eb09235e22995f0116Doris Liu animatorSet.reset(); 1786126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } else { 1787126df850ce6b5f8a355534eb09235e22995f0116Doris Liu throw new UnsupportedOperationException("Animation action " + 1788126df850ce6b5f8a355534eb09235e22995f0116Doris Liu pendingAction + "is not supported"); 1789126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } 1790126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } 1791126df850ce6b5f8a355534eb09235e22995f0116Doris Liu mPendingAnimationActions.clear(); 1792126df850ce6b5f8a355534eb09235e22995f0116Doris Liu } 1793766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu } 1794766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1795766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreateAnimatorSet(); 1796718cd3eb70703c43f29ca37907bbf0e153d8cca0Doris Liu private static native void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr); 1797766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native void nAddAnimator(long setPtr, long propertyValuesHolder, 1798f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu long nativeInterpolator, long startDelay, long duration, int repeatCount, 1799f7167e8f286cff91dec01fdf617bf568f1d100e6Doris Liu int repeatMode); 1800299659ddb7e0c34ca094abe485bcd0989727fc07John Reck private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length); 1801299659ddb7e0c34ca094abe485bcd0989727fc07John Reck private static native void nSetPropertyHolderData(long nativePtr, int[] data, int length); 1802299659ddb7e0c34ca094abe485bcd0989727fc07John Reck private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id); 1803299659ddb7e0c34ca094abe485bcd0989727fc07John Reck private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id); 1804766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu 1805299659ddb7e0c34ca094abe485bcd0989727fc07John Reck // ------------- @FastNative ------------------- 1806299659ddb7e0c34ca094abe485bcd0989727fc07John Reck 1807299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1808766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId, 1809766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float startValue, float endValue); 1810299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1811766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr, 1812766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu long endValuePtr); 1813299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1814766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId, 1815766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu int startValue, int endValue); 1816299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1817766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId, 1818766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float startValue, float endValue); 1819299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1820766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, 1821766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu float endValue); 1822299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1823766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native void nEnd(long animatorSetPtr); 1824299659ddb7e0c34ca094abe485bcd0989727fc07John Reck @FastNative 1825766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu private static native void nReset(long animatorSetPtr); 1826f276acd98457bcaabc9e79a17a736b3b484f005eDoris Liu} 1827