1560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell/* 2560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Copyright (C) 2011 The Android Open Source Project 3560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 4560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * you may not use this file except in compliance with the License. 6560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * You may obtain a copy of the License at 7560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 8560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 10560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Unless required by applicable law or agreed to in writing, software 11560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * See the License for the specific language governing permissions and 14560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * limitations under the License. 15560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 16560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellpackage android.support.v4.widget; 17560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 18560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellimport android.content.Context; 19560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellimport android.graphics.Canvas; 20560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellimport android.os.Build; 21560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 22560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell/** 230574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * Helper for accessing {@link android.widget.EdgeEffect} introduced after 240574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * API level 4 in a backwards compatible fashion. 25560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 260574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * This class is used to access {@link android.widget.EdgeEffect} on platform versions 270574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * that support it. When running on older platforms it will result in no-ops. It should 280574ca37da4619afe4e26753f5a1b4de314b6565Svetoslav Ganov * be used by views that wish to use the standard Android visual effects at the edges 29560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * of scrolling containers. 30560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 31560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powellpublic class EdgeEffectCompat { 32560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell private Object mEdgeEffect; 33560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 34560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell private static final EdgeEffectImpl IMPL; 35560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 36560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell static { 37560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell if (Build.VERSION.SDK_INT >= 14) { // ICS 38560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell IMPL = new EdgeEffectIcsImpl(); 39560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } else { 40560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell IMPL = new BaseEdgeEffectImpl(); 41560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 42560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 43560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 44560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell interface EdgeEffectImpl { 45560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public Object newEdgeEffect(Context context); 46560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void setSize(Object edgeEffect, int width, int height); 47560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean isFinished(Object edgeEffect); 48560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void finish(Object edgeEffect); 49560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onPull(Object edgeEffect, float deltaDistance); 50560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onRelease(Object edgeEffect); 51560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onAbsorb(Object edgeEffect, int velocity); 52560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean draw(Object edgeEffect, Canvas canvas); 53560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 54560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 55560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 56560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Null implementation to use pre-ICS 57560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 58560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell static class BaseEdgeEffectImpl implements EdgeEffectImpl { 59560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public Object newEdgeEffect(Context context) { 60560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return null; 61560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 62560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 63560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void setSize(Object edgeEffect, int width, int height) { 64560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 65560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 66560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean isFinished(Object edgeEffect) { 67560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return true; 68560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 69560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 70560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void finish(Object edgeEffect) { 71560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 72560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 73560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onPull(Object edgeEffect, float deltaDistance) { 74560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return false; 75560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 76560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 77560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onRelease(Object edgeEffect) { 78560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return false; 79560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 80560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 81560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onAbsorb(Object edgeEffect, int velocity) { 82560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return false; 83560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 84560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 85560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean draw(Object edgeEffect, Canvas canvas) { 86560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return false; 87560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 88560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 89560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 90560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell static class EdgeEffectIcsImpl implements EdgeEffectImpl { 91560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public Object newEdgeEffect(Context context) { 92560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.newEdgeEffect(context); 93560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 94560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 95560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void setSize(Object edgeEffect, int width, int height) { 96560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell EdgeEffectCompatIcs.setSize(edgeEffect, width, height); 97560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 98560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 99560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean isFinished(Object edgeEffect) { 100560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.isFinished(edgeEffect); 101560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 102560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 103560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void finish(Object edgeEffect) { 104560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell EdgeEffectCompatIcs.finish(edgeEffect); 105560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 106560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 107560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onPull(Object edgeEffect, float deltaDistance) { 108560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.onPull(edgeEffect, deltaDistance); 109560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 110560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 111560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onRelease(Object edgeEffect) { 112560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.onRelease(edgeEffect); 113560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 114560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 115560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onAbsorb(Object edgeEffect, int velocity) { 116560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.onAbsorb(edgeEffect, velocity); 117560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 118560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 119560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean draw(Object edgeEffect, Canvas canvas) { 120560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return EdgeEffectCompatIcs.draw(edgeEffect, canvas); 121560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 122560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 123560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 124560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 125560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Construct a new EdgeEffect themed using the given context. 126560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 127560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * <p>Note: On platform versions that do not support EdgeEffect, all operations 128560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * on the newly constructed object will be mocked/no-ops.</p> 129560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 130560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param context Context to use for theming the effect 131560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 132560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public EdgeEffectCompat(Context context) { 133560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell mEdgeEffect = IMPL.newEdgeEffect(context); 134560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 135560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 136560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 137560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Set the size of this edge effect in pixels. 138560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 139560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param width Effect width in pixels 140560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param height Effect height in pixels 141560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 142560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void setSize(int width, int height) { 143560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell IMPL.setSize(mEdgeEffect, width, height); 144560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 145560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 146560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 147560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Reports if this EdgeEffectCompat's animation is finished. If this method returns false 148560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * after a call to {@link #draw(Canvas)} the host widget should schedule another 149560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * drawing pass to continue the animation. 150560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 151560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @return true if animation is finished, false if drawing should continue on the next frame. 152560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 153560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean isFinished() { 154560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return IMPL.isFinished(mEdgeEffect); 155560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 156560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 157560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 158560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Immediately finish the current animation. 159560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * After this call {@link #isFinished()} will return true. 160560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 161560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public void finish() { 162560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell IMPL.finish(mEdgeEffect); 163560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 164560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 165560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 166560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * A view should call this when content is pulled away from an edge by the user. 167560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * This will update the state of the current visual effect and its associated animation. 168560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * The host view should always {@link android.view.View#invalidate()} if this method 169560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * returns true and draw the results accordingly. 170560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 171560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to 172560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 1.f (full length of the view) or negative values to express change 173560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * back toward the edge reached to initiate the effect. 174560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @return true if the host view should call invalidate, false if it should not. 175560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 176560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onPull(float deltaDistance) { 177560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return IMPL.onPull(mEdgeEffect, deltaDistance); 178560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 179560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 180560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 181560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Call when the object is released after being pulled. 182560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * This will begin the "decay" phase of the effect. After calling this method 183560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * the host view should {@link android.view.View#invalidate()} if this method 184560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * returns true and thereby draw the results accordingly. 185560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 186560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @return true if the host view should invalidate, false if it should not. 187560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 188560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onRelease() { 189560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return IMPL.onRelease(mEdgeEffect); 190560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 191560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 192560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 193560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Call when the effect absorbs an impact at the given velocity. 194560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Used when a fling reaches the scroll boundary. 195560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 196560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller}, 197560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * the method <code>getCurrVelocity</code> will provide a reasonable approximation 198560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * to use here.</p> 199560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 200560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param velocity Velocity at impact in pixels per second. 201560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @return true if the host view should invalidate, false if it should not. 202560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 203560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean onAbsorb(int velocity) { 204560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return IMPL.onAbsorb(mEdgeEffect, velocity); 205560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 206560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell 207560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell /** 208560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * Draw into the provided canvas. Assumes that the canvas has been rotated 209560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * accordingly and the size has been set. The effect will be drawn the full 210560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * width of X=0 to X=width, beginning from Y=0 and extending to some factor < 211560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 1.f of height. 212560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * 213560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @param canvas Canvas to draw into 214560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * @return true if drawing should continue beyond this frame to continue the 215560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell * animation 216560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell */ 217560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell public boolean draw(Canvas canvas) { 218560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell return IMPL.draw(mEdgeEffect, canvas); 219560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell } 220560114f591be31d0fb73c26a1ee1cc0a15184abaAdam Powell} 221