ViewCompat.java revision 0574ca37da4619afe4e26753f5a1b4de314b6565
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 */ 16 17package android.support.v4.view; 18 19import android.graphics.Rect; 20import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 21import android.view.View; 22import android.view.accessibility.AccessibilityEvent; 23 24/** 25 * Helper for accessing features in {@link View} introduced after API 26 * level 4 in a backwards compatible fashion. 27 */ 28public class ViewCompat { 29 /** 30 * Always allow a user to over-scroll this view, provided it is a 31 * view that can scroll. 32 */ 33 public static final int OVER_SCROLL_ALWAYS = 0; 34 35 /** 36 * Allow a user to over-scroll this view only if the content is large 37 * enough to meaningfully scroll, provided it is a view that can scroll. 38 */ 39 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 40 41 /** 42 * Never allow a user to over-scroll this view. 43 */ 44 public static final int OVER_SCROLL_NEVER = 2; 45 46 interface ViewCompatImpl { 47 public boolean canScrollHorizontally(View v, int direction); 48 public boolean canScrollVertically(View v, int direction); 49 public int getOverScrollMode(View v); 50 public void setOverScrollMode(View v, int mode); 51 public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event); 52 public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event); 53 public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info); 54 public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate); 55 } 56 57 static class BaseViewCompatImpl implements ViewCompatImpl { 58 public boolean canScrollHorizontally(View v, int direction) { 59 return false; 60 } 61 public boolean canScrollVertically(View v, int direction) { 62 return false; 63 } 64 public int getOverScrollMode(View v) { 65 return OVER_SCROLL_NEVER; 66 } 67 public void setOverScrollMode(View v, int mode) { 68 // Do nothing; API doesn't exist 69 } 70 public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) { 71 // Do nothing; API doesn't exist 72 } 73 public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { 74 // Do nothing; API doesn't exist 75 } 76 public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { 77 // Do nothing; API doesn't exist 78 } 79 public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { 80 // Do nothing; API doesn't exist 81 } 82 } 83 84 static class GBViewCompatImpl extends BaseViewCompatImpl { 85 @Override 86 public int getOverScrollMode(View v) { 87 return ViewCompatGingerbread.getOverScrollMode(v); 88 } 89 @Override 90 public void setOverScrollMode(View v, int mode) { 91 ViewCompatGingerbread.setOverScrollMode(v, mode); 92 } 93 } 94 95 static class ICSViewCompatImpl extends GBViewCompatImpl { 96 @Override 97 public boolean canScrollHorizontally(View v, int direction) { 98 return ViewCompatICS.canScrollHorizontally(v, direction); 99 } 100 @Override 101 public boolean canScrollVertically(View v, int direction) { 102 return ViewCompatICS.canScrollVertically(v, direction); 103 } 104 @Override 105 public void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { 106 ViewCompatICS.onPopulateAccessibilityEvent(v, event); 107 } 108 @Override 109 public void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { 110 ViewCompatICS.onInitializeAccessibilityEvent(v, event); 111 } 112 @Override 113 public void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { 114 ViewCompatICS.onInitializeAccessibilityNodeInfo(v, info.getImpl()); 115 } 116 @Override 117 public void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) { 118 ViewCompatICS.setAccessibilityDelegate(v, delegate.getBridge()); 119 } 120 } 121 122 static final ViewCompatImpl IMPL; 123 static { 124 final int version = android.os.Build.VERSION.SDK_INT; 125 if (version >= 14) { 126 IMPL = new ICSViewCompatImpl(); 127 } else if (version >= 9) { 128 IMPL = new GBViewCompatImpl(); 129 } else { 130 IMPL = new BaseViewCompatImpl(); 131 } 132 } 133 134 /** 135 * Check if this view can be scrolled horizontally in a certain direction. 136 * 137 * @param v The View against which to invoke the method. 138 * @param direction Negative to check scrolling left, positive to check scrolling right. 139 * @return true if this view can be scrolled in the specified direction, false otherwise. 140 */ 141 public static boolean canScrollHorizontally(View v, int direction) { 142 return IMPL.canScrollHorizontally(v, direction); 143 } 144 145 /** 146 * Check if this view can be scrolled vertically in a certain direction. 147 * 148 * @param v The View against which to invoke the method. 149 * @param direction Negative to check scrolling up, positive to check scrolling down. 150 * @return true if this view can be scrolled in the specified direction, false otherwise. 151 */ 152 public static boolean canScrollVertically(View v, int direction) { 153 return IMPL.canScrollVertically(v, direction); 154 } 155 156 /** 157 * Returns the over-scroll mode for this view. The result will be 158 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 159 * (allow over-scrolling only if the view content is larger than the container), 160 * or {@link #OVER_SCROLL_NEVER}. 161 * 162 * @param v The View against which to invoke the method. 163 * @return This view's over-scroll mode. 164 */ 165 public static int getOverScrollMode(View v) { 166 return IMPL.getOverScrollMode(v); 167 } 168 169 /** 170 * Set the over-scroll mode for this view. Valid over-scroll modes are 171 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 172 * (allow over-scrolling only if the view content is larger than the container), 173 * or {@link #OVER_SCROLL_NEVER}. 174 * 175 * Setting the over-scroll mode of a view will have an effect only if the 176 * view is capable of scrolling. 177 * 178 * @param v The View against which to invoke the method. 179 * @param overScrollMode The new over-scroll mode for this view. 180 */ 181 public static void setOverScrollMode(View v, int overScrollMode) { 182 IMPL.setOverScrollMode(v, overScrollMode); 183 } 184 185 /** 186 * Called from {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 187 * giving a chance to this View to populate the accessibility event with its 188 * text content. While this method is free to modify event 189 * attributes other than text content, doing so should normally be performed in 190 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)}. 191 * <p> 192 * Example: Adding formatted date string to an accessibility event in addition 193 * to the text added by the super implementation: 194 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 195 * super.onPopulateAccessibilityEvent(event); 196 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 197 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 198 * mCurrentDate.getTimeInMillis(), flags); 199 * event.getText().add(selectedDateUtterance); 200 * }</pre> 201 * <p> 202 * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling 203 * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its 204 * {@link android.view.View.AccessibilityDelegate#onPopulateAccessibilityEvent(View, 205 * AccessibilityEvent)} 206 * is responsible for handling this call. 207 * </p> 208 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 209 * information to the event, in case the default implementation has basic information to add. 210 * </p> 211 * 212 * @param v The View against which to invoke the method. 213 * @param event The accessibility event which to populate. 214 * 215 * @see View#sendAccessibilityEvent(int) 216 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 217 */ 218 public static void onPopulateAccessibilityEvent(View v, AccessibilityEvent event) { 219 IMPL.onPopulateAccessibilityEvent(v, event); 220 } 221 222 /** 223 * Initializes an {@link AccessibilityEvent} with information about 224 * this View which is the event source. In other words, the source of 225 * an accessibility event is the view whose state change triggered firing 226 * the event. 227 * <p> 228 * Example: Setting the password property of an event in addition 229 * to properties set by the super implementation: 230 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 231 * super.onInitializeAccessibilityEvent(event); 232 * event.setPassword(true); 233 * }</pre> 234 * <p> 235 * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling 236 * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its 237 * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityEvent(View, 238 * AccessibilityEvent)} 239 * is responsible for handling this call. 240 * </p> 241 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 242 * information to the event, in case the default implementation has basic information to add. 243 * </p> 244 * 245 * @param v The View against which to invoke the method. 246 * @param event The event to initialize. 247 * 248 * @see View#sendAccessibilityEvent(int) 249 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 250 */ 251 public static void onInitializeAccessibilityEvent(View v, AccessibilityEvent event) { 252 IMPL.onInitializeAccessibilityEvent(v, event); 253 } 254 255 /** 256 * Initializes an {@link android.view.accessibility.AccessibilityNodeInfo} with information 257 * about this view. The base implementation sets: 258 * <ul> 259 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setParent(View)},</li> 260 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 261 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 262 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 263 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClassName(CharSequence)},</li> 264 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 265 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setEnabled(boolean)},</li> 266 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setClickable(boolean)},</li> 267 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocusable(boolean)},</li> 268 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setFocused(boolean)},</li> 269 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setLongClickable(boolean)},</li> 270 * <li>{@link android.view.accessibility.AccessibilityNodeInfo#setSelected(boolean)},</li> 271 * </ul> 272 * <p> 273 * Subclasses should override this method, call the super implementation, 274 * and set additional attributes. 275 * </p> 276 * <p> 277 * If an {@link android.view.View.AccessibilityDelegate} has been specified via calling 278 * {@link View#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)} its 279 * {@link android.view.View.AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, 280 * android.view.accessibility.AccessibilityNodeInfo)} 281 * is responsible for handling this call. 282 * </p> 283 * 284 * @param v The View against which to invoke the method. 285 * @param info The instance to initialize. 286 */ 287 public static void onInitializeAccessibilityNodeInfo(View v, AccessibilityNodeInfoCompat info) { 288 IMPL.onInitializeAccessibilityNodeInfo(v, info); 289 } 290 291 /** 292 * Sets a delegate for implementing accessibility support via compositon as 293 * opposed to inheritance. The delegate's primary use is for implementing 294 * backwards compatible widgets. For more details see 295 * {@link android.view.View.AccessibilityDelegate}. 296 * 297 * @param v The View against which to invoke the method. 298 * @param delegate The delegate instance. 299 * 300 * @see android.view.View.AccessibilityDelegate 301 */ 302 public static void setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) { 303 IMPL.setAccessibilityDelegate(v, delegate); 304 } 305} 306