EdgeEffectCompat.java revision 560114f591be31d0fb73c26a1ee1cc0a15184aba
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.support.v4.widget; 17 18import android.content.Context; 19import android.graphics.Canvas; 20import android.os.Build; 21 22/** 23 * Helper for accessing EdgeEffects from newer platform versions. 24 * 25 * This class is used to access {@link android.widget.EdgeEffect} on platform versions 26 * that support it. When running on older platforms it will result in no-ops. It should 27 * be used by views that wish to use the standard Android visual effects at the edges 28 * of scrolling containers. 29 */ 30public class EdgeEffectCompat { 31 private Object mEdgeEffect; 32 33 private static final EdgeEffectImpl IMPL; 34 35 static { 36 if (Build.VERSION.SDK_INT >= 14) { // ICS 37 IMPL = new EdgeEffectIcsImpl(); 38 } else { 39 IMPL = new BaseEdgeEffectImpl(); 40 } 41 } 42 43 interface EdgeEffectImpl { 44 public Object newEdgeEffect(Context context); 45 public void setSize(Object edgeEffect, int width, int height); 46 public boolean isFinished(Object edgeEffect); 47 public void finish(Object edgeEffect); 48 public boolean onPull(Object edgeEffect, float deltaDistance); 49 public boolean onRelease(Object edgeEffect); 50 public boolean onAbsorb(Object edgeEffect, int velocity); 51 public boolean draw(Object edgeEffect, Canvas canvas); 52 } 53 54 /** 55 * Null implementation to use pre-ICS 56 */ 57 static class BaseEdgeEffectImpl implements EdgeEffectImpl { 58 public Object newEdgeEffect(Context context) { 59 return null; 60 } 61 62 public void setSize(Object edgeEffect, int width, int height) { 63 } 64 65 public boolean isFinished(Object edgeEffect) { 66 return true; 67 } 68 69 public void finish(Object edgeEffect) { 70 } 71 72 public boolean onPull(Object edgeEffect, float deltaDistance) { 73 return false; 74 } 75 76 public boolean onRelease(Object edgeEffect) { 77 return false; 78 } 79 80 public boolean onAbsorb(Object edgeEffect, int velocity) { 81 return false; 82 } 83 84 public boolean draw(Object edgeEffect, Canvas canvas) { 85 return false; 86 } 87 } 88 89 static class EdgeEffectIcsImpl implements EdgeEffectImpl { 90 public Object newEdgeEffect(Context context) { 91 return EdgeEffectCompatIcs.newEdgeEffect(context); 92 } 93 94 public void setSize(Object edgeEffect, int width, int height) { 95 EdgeEffectCompatIcs.setSize(edgeEffect, width, height); 96 } 97 98 public boolean isFinished(Object edgeEffect) { 99 return EdgeEffectCompatIcs.isFinished(edgeEffect); 100 } 101 102 public void finish(Object edgeEffect) { 103 EdgeEffectCompatIcs.finish(edgeEffect); 104 } 105 106 public boolean onPull(Object edgeEffect, float deltaDistance) { 107 return EdgeEffectCompatIcs.onPull(edgeEffect, deltaDistance); 108 } 109 110 public boolean onRelease(Object edgeEffect) { 111 return EdgeEffectCompatIcs.onRelease(edgeEffect); 112 } 113 114 public boolean onAbsorb(Object edgeEffect, int velocity) { 115 return EdgeEffectCompatIcs.onAbsorb(edgeEffect, velocity); 116 } 117 118 public boolean draw(Object edgeEffect, Canvas canvas) { 119 return EdgeEffectCompatIcs.draw(edgeEffect, canvas); 120 } 121 } 122 123 /** 124 * Construct a new EdgeEffect themed using the given context. 125 * 126 * <p>Note: On platform versions that do not support EdgeEffect, all operations 127 * on the newly constructed object will be mocked/no-ops.</p> 128 * 129 * @param context Context to use for theming the effect 130 */ 131 public EdgeEffectCompat(Context context) { 132 mEdgeEffect = IMPL.newEdgeEffect(context); 133 } 134 135 /** 136 * Set the size of this edge effect in pixels. 137 * 138 * @param width Effect width in pixels 139 * @param height Effect height in pixels 140 */ 141 public void setSize(int width, int height) { 142 IMPL.setSize(mEdgeEffect, width, height); 143 } 144 145 /** 146 * Reports if this EdgeEffectCompat's animation is finished. If this method returns false 147 * after a call to {@link #draw(Canvas)} the host widget should schedule another 148 * drawing pass to continue the animation. 149 * 150 * @return true if animation is finished, false if drawing should continue on the next frame. 151 */ 152 public boolean isFinished() { 153 return IMPL.isFinished(mEdgeEffect); 154 } 155 156 /** 157 * Immediately finish the current animation. 158 * After this call {@link #isFinished()} will return true. 159 */ 160 public void finish() { 161 IMPL.finish(mEdgeEffect); 162 } 163 164 /** 165 * A view should call this when content is pulled away from an edge by the user. 166 * This will update the state of the current visual effect and its associated animation. 167 * The host view should always {@link android.view.View#invalidate()} if this method 168 * returns true and draw the results accordingly. 169 * 170 * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to 171 * 1.f (full length of the view) or negative values to express change 172 * back toward the edge reached to initiate the effect. 173 * @return true if the host view should call invalidate, false if it should not. 174 */ 175 public boolean onPull(float deltaDistance) { 176 return IMPL.onPull(mEdgeEffect, deltaDistance); 177 } 178 179 /** 180 * Call when the object is released after being pulled. 181 * This will begin the "decay" phase of the effect. After calling this method 182 * the host view should {@link android.view.View#invalidate()} if this method 183 * returns true and thereby draw the results accordingly. 184 * 185 * @return true if the host view should invalidate, false if it should not. 186 */ 187 public boolean onRelease() { 188 return IMPL.onRelease(mEdgeEffect); 189 } 190 191 /** 192 * Call when the effect absorbs an impact at the given velocity. 193 * Used when a fling reaches the scroll boundary. 194 * 195 * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller}, 196 * the method <code>getCurrVelocity</code> will provide a reasonable approximation 197 * to use here.</p> 198 * 199 * @param velocity Velocity at impact in pixels per second. 200 * @return true if the host view should invalidate, false if it should not. 201 */ 202 public boolean onAbsorb(int velocity) { 203 return IMPL.onAbsorb(mEdgeEffect, velocity); 204 } 205 206 /** 207 * Draw into the provided canvas. Assumes that the canvas has been rotated 208 * accordingly and the size has been set. The effect will be drawn the full 209 * width of X=0 to X=width, beginning from Y=0 and extending to some factor < 210 * 1.f of height. 211 * 212 * @param canvas Canvas to draw into 213 * @return true if drawing should continue beyond this frame to continue the 214 * animation 215 */ 216 public boolean draw(Canvas canvas) { 217 return IMPL.draw(mEdgeEffect, canvas); 218 } 219} 220