RippleComponent.java revision f872ee0057ed247aa93589347f1b53afc99517f8
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; 23f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.view.HardwareCanvas; 24f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport android.view.RenderNodeAnimator; 25f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 26f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteimport java.util.ArrayList; 27f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 28f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette/** 29f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Abstract class that handles hardware/software hand-off and lifecycle for 30f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * animated ripple foreground and background components. 31f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 32f872ee0057ed247aa93589347f1b53afc99517f8Alan Viveretteabstract class RippleComponent { 33f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private final RippleDrawable mOwner; 34f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 35f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Bounds used for computing max radius. May be modified by the owner. */ 36f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final Rect mBounds; 37f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 38f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Whether we can use hardware acceleration for the exit animation. */ 39f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private boolean mHasHardwareCanvas; 40f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 41f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private boolean mHasPendingHardwareAnimator; 42f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private RenderNodeAnimatorSet mHardwareAnimator; 43f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 44f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private Animator mSoftwareAnimator; 45f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 46f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Whether we have an explicit maximum radius. */ 47f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private boolean mHasMaxRadius; 48f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 49f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** How big this ripple should be when fully entered. */ 50f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected float mTargetRadius; 51f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 52f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** Screen density used to adjust pixel-based constants. */ 53f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected float mDensity; 54f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 55f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public RippleComponent(RippleDrawable owner, Rect bounds) { 56f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mOwner = owner; 57f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mBounds = bounds; 58f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 59f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 60f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public final void setup(float maxRadius, float density) { 61f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (maxRadius >= 0) { 62f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasMaxRadius = true; 63f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mTargetRadius = maxRadius; 64f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } else { 65f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfWidth = mBounds.width() / 2.0f; 66f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfHeight = mBounds.height() / 2.0f; 67f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mTargetRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); 68f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 69f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 70f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mDensity = density; 71f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 72f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette onSetup(); 73f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette onTargetRadiusChanged(mTargetRadius); 74f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 75f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 76f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 77f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts a ripple enter animation. 78f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 79f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param fast whether the ripple should enter quickly 80f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 81f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public final void enter(boolean fast) { 82f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancel(); 83f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 84f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator = createSoftwareEnter(fast); 85f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.start(); 86f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 87f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 88f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 89f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts a ripple exit animation. 90f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 91f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public final void exit() { 92f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancel(); 93f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 94f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasHardwareCanvas) { 95f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // We don't have access to a canvas here, but we expect one on the 96f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // next frame. We'll start the render thread animation then. 97f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = true; 98f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 99f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Request another frame. 100f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette invalidateSelf(); 101f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } else { 102f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator = createSoftwareExit(); 103f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.start(); 104f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 105f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 106f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 107f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 108f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Cancels all animations. Software animation values are left in the 109f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * current state, while hardware animation values jump to the end state. 110f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 111f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void cancel() { 112f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette cancelSoftwareAnimations(); 113f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 114f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 115f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 116f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 117f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends all animations, jumping values to the end state. 118f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 119f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void end() { 120f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endSoftwareAnimations(); 121f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 122f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 123f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 124f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 125f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Draws the ripple to the canvas, inheriting the paint's color and alpha 126f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * properties. 127f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 128f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param c the canvas to which the ripple should be drawn 129f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param p the paint used to draw the ripple 130f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @return {@code true} if something was drawn, {@code false} otherwise 131f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 132f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public boolean draw(Canvas c, Paint p) { 133f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final boolean hasHardwareCanvas = c.isHardwareAccelerated() 134f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette && c instanceof HardwareCanvas; 135f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasHardwareCanvas != hasHardwareCanvas) { 136f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasHardwareCanvas = hasHardwareCanvas; 137f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 138f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (!hasHardwareCanvas) { 139f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // We've switched from hardware to non-hardware mode. Panic. 140f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette endHardwareAnimations(); 141f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 142f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 143f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 144f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (hasHardwareCanvas) { 145f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final HardwareCanvas hw = (HardwareCanvas) c; 146f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette startPendingAnimation(hw, p); 147f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 148f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHardwareAnimator != null) { 149f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return drawHardware(hw); 150f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 151f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 152f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 153f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return drawSoftware(c, p); 154f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 155f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 156f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 157f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Populates {@code bounds} with the maximum drawing bounds of the ripple 158f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * relative to its center. The resulting bounds should be translated into 159f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * parent drawable coordinates before use. 160f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 161f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param bounds the rect to populate with drawing bounds 162f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 163f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void getBounds(Rect bounds) { 164f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int r = (int) Math.ceil(mTargetRadius); 165f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette bounds.set(-r, -r, r, r); 166f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 167f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 168f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 169f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Starts the pending hardware animation, if available. 170f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 171f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param hw hardware canvas on which the animation should draw 172f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param p paint whose properties the hardware canvas should use 173f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 174f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void startPendingAnimation(HardwareCanvas hw, Paint p) { 175f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasPendingHardwareAnimator) { 176f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = false; 177f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 178f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator = createHardwareExit(new Paint(p)); 179f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator.start(hw); 180f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 181f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Preemptively jump the software values to the end state now that 182f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // the hardware exit has read whatever values it needs. 183f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette jumpValuesToExit(); 184f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 185f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 186f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 187f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 188f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Cancels any current software animations, leaving the values in their 189f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * current state. 190f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 191f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void cancelSoftwareAnimations() { 192f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mSoftwareAnimator != null) { 193f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.cancel(); 194f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 195f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 196f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 197f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 198f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends any current software animations, jumping the values to their end 199f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * state. 200f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 201f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void endSoftwareAnimations() { 202f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mSoftwareAnimator != null) { 203f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mSoftwareAnimator.end(); 204f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 205f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 206f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 207f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 208f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Ends any pending or current hardware animations. 209f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * <p> 210f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Hardware animations can't synchronize values back to the software 211f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * thread, so there is no "cancel" equivalent. 212f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 213f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private void endHardwareAnimations() { 214f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHardwareAnimator != null) { 215f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator.end(); 216f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHardwareAnimator = null; 217f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 218f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 219f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (mHasPendingHardwareAnimator) { 220f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mHasPendingHardwareAnimator = false; 221f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 222f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 223f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 224f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final void invalidateSelf() { 225f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mOwner.invalidateSelf(); 226f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 227f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 228f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final boolean isHardwareAnimating() { 229f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return mHardwareAnimator != null && mHardwareAnimator.isRunning() 230f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette || mHasPendingHardwareAnimator; 231f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 232f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 233f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected final void onHotspotBoundsChanged() { 234f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (!mHasMaxRadius) { 235f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfWidth = mBounds.width() / 2.0f; 236f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float halfHeight = mBounds.height() / 2.0f; 237f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final float targetRadius = (float) Math.sqrt(halfWidth * halfWidth 238f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette + halfHeight * halfHeight); 239f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 240f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette onTargetRadiusChanged(targetRadius); 241f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 242f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 243f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 244f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 245f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Called when the target radius changes. 246f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * 247f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * @param targetRadius the new target radius 248f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 249f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected void onTargetRadiusChanged(float targetRadius) { 250f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Stub. 251f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 252f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 253f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 254f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Called during ripple setup, which occurs before the first enter 255f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * animation. 256f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 257f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected void onSetup() { 258f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette // Stub. 259f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 260f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 261f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract Animator createSoftwareEnter(boolean fast); 262f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 263f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract Animator createSoftwareExit(); 264f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 265f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract RenderNodeAnimatorSet createHardwareExit(Paint p); 266f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 267f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract boolean drawHardware(HardwareCanvas c); 268f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 269f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract boolean drawSoftware(Canvas c, Paint p); 270f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 271f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette /** 272f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * Called when the hardware exit is cancelled. Jumps software values to end 273f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette * state to ensure that software and hardware values are synchronized. 274f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette */ 275f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette protected abstract void jumpValuesToExit(); 276f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 277f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public static class RenderNodeAnimatorSet { 278f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette private final ArrayList<RenderNodeAnimator> mAnimators = new ArrayList<>(); 279f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 280f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void add(RenderNodeAnimator anim) { 281f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mAnimators.add(anim); 282f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 283f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 284f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void clear() { 285f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette mAnimators.clear(); 286f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 287f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 288f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void start(HardwareCanvas target) { 289f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (target == null) { 290f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette throw new IllegalArgumentException("Hardware canvas must be non-null"); 291f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 292f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 293f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 294f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 295f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 296f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 297f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.setTarget(target); 298f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.start(); 299f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 300f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 301f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 302f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void cancel() { 303f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 304f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 305f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 306f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 307f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette anim.cancel(); 308f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 309f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 310f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 311f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public void end() { 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.end(); 317f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 318f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 319f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette 320f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette public boolean isRunning() { 321f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final ArrayList<RenderNodeAnimator> animators = mAnimators; 322f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final int N = animators.size(); 323f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette for (int i = 0; i < N; i++) { 324f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette final RenderNodeAnimator anim = animators.get(i); 325f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette if (anim.isRunning()) { 326f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return true; 327f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 328f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 329f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette return false; 330f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 331f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette } 332f872ee0057ed247aa93589347f1b53afc99517f8Alan Viverette} 333