1532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang/* 2532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Copyright (C) 2011 The Android Open Source Project 3532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 4532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 5532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * you may not use this file except in compliance with the License. 6532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * You may obtain a copy of the License at 7532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 8532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 9532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 10532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Unless required by applicable law or agreed to in writing, software 11532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 12532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * See the License for the specific language governing permissions and 14532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * limitations under the License. 15532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 16532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 17532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changpackage com.android.gallery3d.ui; 18532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 19532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changimport android.content.Context; 202b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport android.graphics.Canvas; 21532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changimport android.graphics.Rect; 22532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changimport android.view.animation.DecelerateInterpolator; 23532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changimport android.view.animation.Interpolator; 24532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 252b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.R; 262b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 27532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// This is copied from android.widget.EdgeEffect with some small modifications: 28532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// (1) Copy the images (overscroll_{edge|glow}.png) to local resources. 29532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// (2) Use "GLCanvas" instead of "Canvas" for draw()'s parameter. 30532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// (3) Use a private Drawable class (which inherits from ResourceTexture) 31532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// instead of android.graphics.drawable.Drawable to hold the images. 32532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// The private Drawable class is used to translate original Canvas calls to 33532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang// corresponding GLCanvas calls. 34532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 35532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang/** 36532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * This class performs the graphical effect used at the edges of scrollable widgets 37532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * when the user scrolls beyond the content bounds in 2D space. 38532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 39532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * <p>EdgeEffect is stateful. Custom widgets using EdgeEffect should create an 40532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * instance for each edge that should show the effect, feed it input data using 41532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * the methods {@link #onAbsorb(int)}, {@link #onPull(float)}, and {@link #onRelease()}, 42532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * and draw the effect using {@link #draw(Canvas)} in the widget's overridden 43532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * {@link android.view.View#draw(Canvas)} method. If {@link #isFinished()} returns 44532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * false after drawing, the edge effect's animation is not yet complete and the widget 45532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * should schedule another drawing pass to continue the animation.</p> 46532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 47532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * <p>When drawing, widgets should draw their main content and child views first, 48532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * usually by invoking <code>super.draw(canvas)</code> from an overridden <code>draw</code> 49532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * method. (This will invoke onDraw and dispatch drawing to child views as needed.) 50532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * The edge effect may then be drawn on top of the view's content using the 51532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * {@link #draw(Canvas)} method.</p> 52532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 53532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Changpublic class EdgeEffect { 547817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 55532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final String TAG = "EdgeEffect"; 56532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 57532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Time it will take the effect to fully recede in ms 58532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int RECEDE_TIME = 1000; 59532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 60532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Time it will take before a pulled glow begins receding in ms 61532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int PULL_TIME = 167; 62532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 63532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Time it will take in ms for a pulled glow to decay to partial strength before release 64532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int PULL_DECAY_TIME = 1000; 65532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 66532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float MAX_ALPHA = 0.8f; 67532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float HELD_EDGE_ALPHA = 0.7f; 68532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float HELD_EDGE_SCALE_Y = 0.5f; 69532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float HELD_GLOW_ALPHA = 0.5f; 70532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float HELD_GLOW_SCALE_Y = 0.5f; 71532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 72532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float MAX_GLOW_HEIGHT = 4.f; 73532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 74532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float PULL_GLOW_BEGIN = 1.f; 75532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float PULL_EDGE_BEGIN = 0.6f; 76532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 77532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Minimum velocity that will be absorbed 78532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int MIN_VELOCITY = 100; 79532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 80532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float EPSILON = 0.001f; 81532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 82532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private final Drawable mEdge; 83532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private final Drawable mGlow; 84532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private int mWidth; 85532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private int mHeight; 86532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private final int MIN_WIDTH = 300; 87532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private final int mMinWidth; 88532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 89532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeAlpha; 90532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeScaleY; 91532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowAlpha; 92532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowScaleY; 93532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 94532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeAlphaStart; 95532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeAlphaFinish; 96532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeScaleYStart; 97532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mEdgeScaleYFinish; 98532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowAlphaStart; 99532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowAlphaFinish; 100532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowScaleYStart; 101532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mGlowScaleYFinish; 102532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 103532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private long mStartTime; 104532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mDuration; 105532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 106532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private final Interpolator mInterpolator; 107532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 108532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int STATE_IDLE = 0; 109532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int STATE_PULL = 1; 110532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int STATE_ABSORB = 2; 111532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int STATE_RECEDE = 3; 112532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int STATE_PULL_DECAY = 4; 113532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 114532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // How much dragging should effect the height of the edge image. 115532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Number determined by user testing. 116532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int PULL_DISTANCE_EDGE_FACTOR = 7; 117532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 118532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // How much dragging should effect the height of the glow image. 119532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Number determined by user testing. 120532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int PULL_DISTANCE_GLOW_FACTOR = 7; 121532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f; 122532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 123532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int VELOCITY_EDGE_FACTOR = 8; 124532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static final int VELOCITY_GLOW_FACTOR = 16; 125532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 126532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private int mState = STATE_IDLE; 127532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 128532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private float mPullDistance; 129532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 130532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 131532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Construct a new EdgeEffect with a theme appropriate for the provided context. 132532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param context Context used to provide theming and resource information for the EdgeEffect 133532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 134532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public EdgeEffect(Context context) { 135532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdge = new Drawable(context, R.drawable.overscroll_edge); 136532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlow = new Drawable(context, R.drawable.overscroll_glow); 137532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 138532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mMinWidth = (int) (context.getResources().getDisplayMetrics().density * MIN_WIDTH + 0.5f); 139532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mInterpolator = new DecelerateInterpolator(); 140532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 141532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 142532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 143532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Set the size of this edge effect in pixels. 144532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 145532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param width Effect width in pixels 146532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param height Effect height in pixels 147532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 148532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void setSize(int width, int height) { 149532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mWidth = width; 150532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mHeight = height; 151532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 152532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 153532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 154532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Reports if this EdgeEffect's animation is finished. If this method returns false 155532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * after a call to {@link #draw(Canvas)} the host widget should schedule another 156532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * drawing pass to continue the animation. 157532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 158532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @return true if animation is finished, false if drawing should continue on the next frame. 159532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 160532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public boolean isFinished() { 161532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return mState == STATE_IDLE; 162532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 163532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 164532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 165532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Immediately finish the current animation. 166532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * After this call {@link #isFinished()} will return true. 167532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 168532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void finish() { 169532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_IDLE; 170532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 171532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 172532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 173532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * A view should call this when content is pulled away from an edge by the user. 174532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * This will update the state of the current visual effect and its associated animation. 175532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * The host view should always {@link android.view.View#invalidate()} after this 176532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * and draw the results accordingly. 177532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 178532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to 179532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 1.f (full length of the view) or negative values to express change 180532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * back toward the edge reached to initiate the effect. 181532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 182532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void onPull(float deltaDistance) { 1837d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang final long now = AnimationTime.get(); 184532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) { 185532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return; 186532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 187532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mState != STATE_PULL) { 188532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleY = PULL_GLOW_BEGIN; 189532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 190532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_PULL; 191532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 192532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mStartTime = now; 193532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mDuration = PULL_TIME; 194532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 195532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mPullDistance += deltaDistance; 196532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang float distance = Math.abs(mPullDistance); 197532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 198532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA)); 199532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleY = mEdgeScaleYStart = Math.max( 200532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f)); 201532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 202532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA, 203532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlpha + 204532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR)); 205532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 206532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang float glowChange = Math.abs(deltaDistance); 207532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (deltaDistance > 0 && mPullDistance < 0) { 208532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang glowChange = -glowChange; 209532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 210532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mPullDistance == 0) { 211532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleY = 0; 212532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 213532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 214532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Do not allow glow to get larger than MAX_GLOW_HEIGHT. 215532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max( 216532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR)); 217532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 218532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaFinish = mEdgeAlpha; 219532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYFinish = mEdgeScaleY; 220532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaFinish = mGlowAlpha; 221532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYFinish = mGlowScaleY; 222532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 223532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 224532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 225532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Call when the object is released after being pulled. 226532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * This will begin the "decay" phase of the effect. After calling this method 227532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * the host view should {@link android.view.View#invalidate()} and thereby 228532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * draw the results accordingly. 229532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 230532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void onRelease() { 231532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mPullDistance = 0; 232532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 233532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mState != STATE_PULL && mState != STATE_PULL_DECAY) { 234532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return; 235532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 236532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 237532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_RECEDE; 238532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaStart = mEdgeAlpha; 239532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYStart = mEdgeScaleY; 240532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaStart = mGlowAlpha; 241532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYStart = mGlowScaleY; 242532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 243532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaFinish = 0.f; 244532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYFinish = 0.f; 245532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaFinish = 0.f; 246532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYFinish = 0.f; 247532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 2487d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang mStartTime = AnimationTime.get(); 249532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mDuration = RECEDE_TIME; 250532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 251532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 252532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 253532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Call when the effect absorbs an impact at the given velocity. 254532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Used when a fling reaches the scroll boundary. 255532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 256532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller}, 257532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * the method <code>getCurrVelocity</code> will provide a reasonable approximation 258532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * to use here.</p> 259532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 260532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param velocity Velocity at impact in pixels per second. 261532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 262532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void onAbsorb(int velocity) { 263532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_ABSORB; 264532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang velocity = Math.max(MIN_VELOCITY, Math.abs(velocity)); 265532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 2667d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang mStartTime = AnimationTime.get(); 267532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mDuration = 0.1f + (velocity * 0.03f); 268532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 269532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // The edge should always be at least partially visible, regardless 270532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // of velocity. 271532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaStart = 0.f; 272532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleY = mEdgeScaleYStart = 0.f; 273532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // The glow depends more on the velocity, and therefore starts out 274532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // nearly invisible. 275532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaStart = 0.5f; 276532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYStart = 0.f; 277532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 278532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Factor the velocity by 8. Testing on device shows this works best to 279532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // reflect the strength of the user's scrolling. 280532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1)); 281532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Edge should never get larger than the size of its asset. 282532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYFinish = Math.max( 283532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f)); 284532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 285532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Growth for the size of the glow should be quadratic to properly 286532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // respond 287532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // to a user's scrolling speed. The faster the scrolling speed, the more 288532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // intense the effect should be for both the size and the saturation. 289532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f); 290532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Alpha should change for the glow as well as size. 291532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaFinish = Math.max( 292532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA)); 293532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 294532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 295532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 296532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang /** 297532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * Draw into the provided canvas. Assumes that the canvas has been rotated 298532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * accordingly and the size has been set. The effect will be drawn the full 299532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * width of X=0 to X=width, beginning from Y=0 and extending to some factor < 300532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 1.f of height. 301532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * 302532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @param canvas Canvas to draw into 303532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * @return true if drawing should continue beyond this frame to continue the 304532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang * animation 305532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang */ 306532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public boolean draw(GLCanvas canvas) { 307532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang update(); 308532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 309532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final int edgeHeight = mEdge.getIntrinsicHeight(); 310532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final int edgeWidth = mEdge.getIntrinsicWidth(); 311532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final int glowHeight = mGlow.getIntrinsicHeight(); 312532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final int glowWidth = mGlow.getIntrinsicWidth(); 313532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 314532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255)); 315532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 316532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang int glowBottom = (int) Math.min( 317532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang glowHeight * mGlowScaleY * glowHeight/ glowWidth * 0.6f, 318532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang glowHeight * MAX_GLOW_HEIGHT); 319532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mWidth < mMinWidth) { 320532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Center the glow and clip it. 321532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang int glowLeft = (mWidth - mMinWidth)/2; 322532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom); 323532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } else { 324532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Stretch the glow to fit. 325532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlow.setBounds(0, 0, mWidth, glowBottom); 326532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 327532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 328532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlow.draw(canvas); 329532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 330532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255)); 331532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 332532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang int edgeBottom = (int) (edgeHeight * mEdgeScaleY); 333532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (mWidth < mMinWidth) { 334532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Center the edge and clip it. 335532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang int edgeLeft = (mWidth - mMinWidth)/2; 336532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom); 337532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } else { 338532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // Stretch the edge to fit. 339532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdge.setBounds(0, 0, mWidth, edgeBottom); 340532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 341532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdge.draw(canvas); 342532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 343532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return mState != STATE_IDLE; 344532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 345532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 346532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private void update() { 3477d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang final long time = AnimationTime.get(); 348532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final float t = Math.min((time - mStartTime) / mDuration, 1.f); 349532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 350532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang final float interp = mInterpolator.getInterpolation(t); 351532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 352532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlpha = mEdgeAlphaStart + (mEdgeAlphaFinish - mEdgeAlphaStart) * interp; 353532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp; 354532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp; 355532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp; 356532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 357532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang if (t >= 1.f - EPSILON) { 358532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang switch (mState) { 359532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang case STATE_ABSORB: 360532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_RECEDE; 3617d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang mStartTime = AnimationTime.get(); 362532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mDuration = RECEDE_TIME; 363532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 364532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaStart = mEdgeAlpha; 365532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYStart = mEdgeScaleY; 366532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaStart = mGlowAlpha; 367532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYStart = mGlowScaleY; 368532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 369532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // After absorb, the glow and edge should fade to nothing. 370532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaFinish = 0.f; 371532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYFinish = 0.f; 372532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaFinish = 0.f; 373532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYFinish = 0.f; 374532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang break; 375532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang case STATE_PULL: 376532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_PULL_DECAY; 3777d19f7f4281f232b9dceee4a5df390c03e2bd16bChih-Chung Chang mStartTime = AnimationTime.get(); 378532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mDuration = PULL_DECAY_TIME; 379532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 380532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaStart = mEdgeAlpha; 381532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYStart = mEdgeScaleY; 382532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaStart = mGlowAlpha; 383532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYStart = mGlowScaleY; 384532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 385532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // After pull, the glow and edge should fade to nothing. 386532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeAlphaFinish = 0.f; 387532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleYFinish = 0.f; 388532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowAlphaFinish = 0.f; 389532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mGlowScaleYFinish = 0.f; 390532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang break; 391532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang case STATE_PULL_DECAY: 392532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // When receding, we want edge to decrease more slowly 393532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang // than the glow. 394532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang float factor = mGlowScaleYFinish != 0 ? 1 395532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang / (mGlowScaleYFinish * mGlowScaleYFinish) 396532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang : Float.MAX_VALUE; 397532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mEdgeScaleY = mEdgeScaleYStart + 398532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang (mEdgeScaleYFinish - mEdgeScaleYStart) * 399532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang interp * factor; 400532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_RECEDE; 401532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang break; 402532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang case STATE_RECEDE: 403532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mState = STATE_IDLE; 404532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang break; 405532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 406532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 407532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 408532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 409532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private static class Drawable extends ResourceTexture { 410532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private Rect mBounds = new Rect(); 411532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang private int mAlpha = 255; 412532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 413532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public Drawable(Context context, int resId) { 414532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang super(context, resId); 415532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 416532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 417532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public int getIntrinsicWidth() { 418532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return getWidth(); 419532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 420532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 421532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public int getIntrinsicHeight() { 422532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang return getHeight(); 423532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 424532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 425532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void setBounds(int left, int top, int right, int bottom) { 426532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mBounds.set(left, top, right, bottom); 427532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 428532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 429532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void setAlpha(int alpha) { 430532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang mAlpha = alpha; 431532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 432532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang 433532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang public void draw(GLCanvas canvas) { 434532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang canvas.save(GLCanvas.SAVE_FLAG_ALPHA); 435532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang canvas.multiplyAlpha(mAlpha / 255.0f); 436532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang Rect b = mBounds; 437532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang draw(canvas, b.left, b.top, b.width(), b.height()); 438532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang canvas.restore(); 439532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 440532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang } 441532d93caddc91a7aa33ca113adbc0b8255d498ebChih-Chung Chang} 442