1f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette/* 2f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Copyright (C) 2015 The Android Open Source Project 3f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 4f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License"); 5f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * you may not use this file except in compliance with the License. 6f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * You may obtain a copy of the License at 7f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 8f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * http://www.apache.org/licenses/LICENSE-2.0 9f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 10f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Unless required by applicable law or agreed to in writing, software 11f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS, 12f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * See the License for the specific language governing permissions and 14f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * limitations under the License. 15f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 16f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 17f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverettepackage android.graphics.drawable; 18f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 19f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.animation.Animator; 20f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Canvas; 21f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Paint; 22f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.graphics.Rect; 23bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viveretteimport android.util.DisplayMetrics; 24f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craikimport android.view.DisplayListCanvas; 25f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.view.RenderNodeAnimator; 26f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 27f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport java.util.ArrayList; 28f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 29f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette/** 30f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Abstract class that handles hardware/software hand-off and lifecycle for 31f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * animated ripple foreground and background components. 32f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 33f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteabstract class RippleComponent { 34f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private final RippleDrawable mOwner; 35f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 36f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Bounds used for computing max radius. May be modified by the owner. */ 37f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final Rect mBounds; 38f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 39f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Whether we can use hardware acceleration for the exit animation. */ 40f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik private boolean mHasDisplayListCanvas; 41f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 42f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private boolean mHasPendingHardwareAnimator; 43f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private RenderNodeAnimatorSet mHardwareAnimator; 44f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 45f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private Animator mSoftwareAnimator; 46f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 47f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Whether we have an explicit maximum radius. */ 48f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private boolean mHasMaxRadius; 49f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 50f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** How big this ripple should be when fully entered. */ 51f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected float mTargetRadius; 52f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 53f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Screen density used to adjust pixel-based constants. */ 54bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette protected float mDensityScale; 55f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 56b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi /** 57b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi * If set, force all ripple animations to not run on RenderThread, even if it would be 58b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi * available. 59b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi */ 60b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi private final boolean mForceSoftware; 61b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi 62b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi public RippleComponent(RippleDrawable owner, Rect bounds, boolean forceSoftware) { 63f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mOwner = owner; 64f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mBounds = bounds; 65b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi mForceSoftware = forceSoftware; 66f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 67f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 685bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette public void onBoundsChange() { 695bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette if (!mHasMaxRadius) { 705bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette mTargetRadius = getTargetRadius(mBounds); 715bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette onTargetRadiusChanged(mTargetRadius); 725bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette } 735bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette } 745bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette 75bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette public final void setup(float maxRadius, int densityDpi) { 76f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (maxRadius >= 0) { 77f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasMaxRadius = true; 78f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mTargetRadius = maxRadius; 79f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } else { 805bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette mTargetRadius = getTargetRadius(mBounds); 81f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 82f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 83bd5294bcb857a48ad22ddd54b13208ec2903c3f6Alan Viverette mDensityScale = densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 84f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 85f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette onTargetRadiusChanged(mTargetRadius); 86f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 87f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 885bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette private static float getTargetRadius(Rect bounds) { 895bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette final float halfWidth = bounds.width() / 2.0f; 905bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette final float halfHeight = bounds.height() / 2.0f; 915bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette return (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); 925bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette } 935bc0144302bb378e5f007baa4bf6620ab9031879Alan Viverette 94f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 95f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts a ripple enter animation. 96f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 97f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param fast whether the ripple should enter quickly 98f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 99f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public final void enter(boolean fast) { 100f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancel(); 101f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 102f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator = createSoftwareEnter(fast); 1036a67db41388165aca63d0d5de2830cc096ed930bAlan Viverette 1046a67db41388165aca63d0d5de2830cc096ed930bAlan Viverette if (mSoftwareAnimator != null) { 1056a67db41388165aca63d0d5de2830cc096ed930bAlan Viverette mSoftwareAnimator.start(); 1066a67db41388165aca63d0d5de2830cc096ed930bAlan Viverette } 107f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 108f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 109f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 110f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts a ripple exit animation. 111f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 112f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public final void exit() { 113f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancel(); 114f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 115f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik if (mHasDisplayListCanvas) { 116f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // We don't have access to a canvas here, but we expect one on the 117f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // next frame. We'll start the render thread animation then. 118f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = true; 119f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 120f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Request another frame. 121f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette invalidateSelf(); 122f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } else { 123f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator = createSoftwareExit(); 124f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.start(); 125f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 126f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 127f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 128f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 129f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Cancels all animations. Software animation values are left in the 130f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * current state, while hardware animation values jump to the end state. 131f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 132f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void cancel() { 133f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancelSoftwareAnimations(); 134f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 135f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 136f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 137f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 138f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends all animations, jumping values to the end state. 139f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 140f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void end() { 141f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endSoftwareAnimations(); 142f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 143f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 144f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 145f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 146f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Draws the ripple to the canvas, inheriting the paint's color and alpha 147f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * properties. 148f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 149f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param c the canvas to which the ripple should be drawn 150f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param p the paint used to draw the ripple 151f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @return {@code true} if something was drawn, {@code false} otherwise 152f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 153f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public boolean draw(Canvas c, Paint p) { 154b7303a36baf8d0ac3efdeeee3310ef5974ba9ceaJorim Jaggi final boolean hasDisplayListCanvas = !mForceSoftware && c.isHardwareAccelerated() 155f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik && c instanceof DisplayListCanvas; 156f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik if (mHasDisplayListCanvas != hasDisplayListCanvas) { 157f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik mHasDisplayListCanvas = hasDisplayListCanvas; 158f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 159f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik if (!hasDisplayListCanvas) { 160f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // We've switched from hardware to non-hardware mode. Panic. 161f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 162f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 163f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 164f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 165f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik if (hasDisplayListCanvas) { 166f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik final DisplayListCanvas hw = (DisplayListCanvas) c; 167f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette startPendingAnimation(hw, p); 168f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 169f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHardwareAnimator != null) { 170f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return drawHardware(hw); 171f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 172f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 173f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 174f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return drawSoftware(c, p); 175f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 176f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 177f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 178f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Populates {@code bounds} with the maximum drawing bounds of the ripple 179f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * relative to its center. The resulting bounds should be translated into 180f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * parent drawable coordinates before use. 181f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 182f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param bounds the rect to populate with drawing bounds 183f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 184f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void getBounds(Rect bounds) { 185f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int r = (int) Math.ceil(mTargetRadius); 186f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette bounds.set(-r, -r, r, r); 187f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 188f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 189f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 190f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts the pending hardware animation, if available. 191f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 192f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param hw hardware canvas on which the animation should draw 193f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param p paint whose properties the hardware canvas should use 194f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 195f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik private void startPendingAnimation(DisplayListCanvas hw, Paint p) { 196f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasPendingHardwareAnimator) { 197f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = false; 198f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 199f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator = createHardwareExit(new Paint(p)); 200f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator.start(hw); 201f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 202f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Preemptively jump the software values to the end state now that 203f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // the hardware exit has read whatever values it needs. 204f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette jumpValuesToExit(); 205f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 206f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 207f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 208f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 209f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Cancels any current software animations, leaving the values in their 210f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * current state. 211f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 212f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void cancelSoftwareAnimations() { 213f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mSoftwareAnimator != null) { 214f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.cancel(); 215fc8882f1340055e00f6c21449983e92413045275Alan Viverette mSoftwareAnimator = null; 216f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 217f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 218f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 219f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 220f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends any current software animations, jumping the values to their end 221f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * state. 222f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 223f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void endSoftwareAnimations() { 224f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mSoftwareAnimator != null) { 225f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.end(); 226fc8882f1340055e00f6c21449983e92413045275Alan Viverette mSoftwareAnimator = null; 227f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 228f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 229f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 230f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 231f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends any pending or current hardware animations. 232f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * <p> 233f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Hardware animations can't synchronize values back to the software 234f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * thread, so there is no "cancel" equivalent. 235f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 236f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void endHardwareAnimations() { 237f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHardwareAnimator != null) { 238f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator.end(); 239f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator = null; 240f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 241f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 242f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasPendingHardwareAnimator) { 243f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = false; 244c3b68dff1654f95a9512027b29e8da49a15f4194Alan Viverette 245c3b68dff1654f95a9512027b29e8da49a15f4194Alan Viverette // Manually jump values to their exited state. Normally we'd do that 246c3b68dff1654f95a9512027b29e8da49a15f4194Alan Viverette // later when starting the hardware exit, but we're aborting early. 247c3b68dff1654f95a9512027b29e8da49a15f4194Alan Viverette jumpValuesToExit(); 248f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 249f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 250f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 251f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final void invalidateSelf() { 25215ce834e52806378d6ab2b90f573bae14cb3fd4bAlan Viverette mOwner.invalidateSelf(false); 253f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 254f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 255f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final boolean isHardwareAnimating() { 256f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return mHardwareAnimator != null && mHardwareAnimator.isRunning() 257f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette || mHasPendingHardwareAnimator; 258f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 259f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 260f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final void onHotspotBoundsChanged() { 261f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (!mHasMaxRadius) { 262f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfWidth = mBounds.width() / 2.0f; 263f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfHeight = mBounds.height() / 2.0f; 264f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float targetRadius = (float) Math.sqrt(halfWidth * halfWidth 265f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette + halfHeight * halfHeight); 266f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 267f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette onTargetRadiusChanged(targetRadius); 268f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 269f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 270f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 271f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 272f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Called when the target radius changes. 273f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 274f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param targetRadius the new target radius 275f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 276f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected void onTargetRadiusChanged(float targetRadius) { 277f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Stub. 278f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 279f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 280f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract Animator createSoftwareEnter(boolean fast); 281f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 282f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract Animator createSoftwareExit(); 283f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 284f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract RenderNodeAnimatorSet createHardwareExit(Paint p); 285f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 286f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik protected abstract boolean drawHardware(DisplayListCanvas c); 287f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 288f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract boolean drawSoftware(Canvas c, Paint p); 289f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 290f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 291f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Called when the hardware exit is cancelled. Jumps software values to end 292f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * state to ensure that software and hardware values are synchronized. 293f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 294f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract void jumpValuesToExit(); 295f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 296f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public static class RenderNodeAnimatorSet { 297f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private final ArrayList<RenderNodeAnimator> mAnimators = new ArrayList<>(); 298f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 299f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void add(RenderNodeAnimator anim) { 300f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mAnimators.add(anim); 301f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 302f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 303f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void clear() { 304f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mAnimators.clear(); 305f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 306f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 307f6829a0a618b4523619ec53c996b04d67e3186b9Chris Craik public void start(DisplayListCanvas target) { 308f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (target == null) { 309f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette throw new IllegalArgumentException("Hardware canvas must be non-null"); 310f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 311f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 312f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 313f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 314f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 315f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 316f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.setTarget(target); 317f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.start(); 318f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 319f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 320f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 321f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void cancel() { 322f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 323f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 324f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 325f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 326f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.cancel(); 327f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 328f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 329f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 330f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void end() { 331f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 332f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 333f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 334f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 335f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.end(); 336f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 337f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 338f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 339f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public boolean isRunning() { 340f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 341f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 342f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 343f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 344f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (anim.isRunning()) { 345f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return true; 346f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 347f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 348f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return false; 349f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 350f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 351f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette} 352