1 /* 2 * Copyright (C) 2012 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 17 package android.support.v4.view.accessibility; 18 19 import android.os.Build; 20 import android.os.Bundle; 21 import android.support.annotation.Nullable; 22 import android.view.View; 23 24 import java.util.ArrayList; 25 import java.util.List; 26 27 /** 28 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeProvider} 29 * introduced after API level 4 in a backwards compatible fashion. 30 */ 31 public class AccessibilityNodeProviderCompat { 32 33 interface AccessibilityNodeProviderImpl { newAccessibilityNodeProviderBridge(AccessibilityNodeProviderCompat compat)34 Object newAccessibilityNodeProviderBridge(AccessibilityNodeProviderCompat compat); 35 } 36 37 static class AccessibilityNodeProviderStubImpl implements AccessibilityNodeProviderImpl { 38 @Override newAccessibilityNodeProviderBridge(AccessibilityNodeProviderCompat compat)39 public Object newAccessibilityNodeProviderBridge(AccessibilityNodeProviderCompat compat) { 40 return null; 41 } 42 } 43 44 private static class AccessibilityNodeProviderJellyBeanImpl 45 extends AccessibilityNodeProviderStubImpl { 46 @Override newAccessibilityNodeProviderBridge( final AccessibilityNodeProviderCompat compat)47 public Object newAccessibilityNodeProviderBridge( 48 final AccessibilityNodeProviderCompat compat) { 49 return AccessibilityNodeProviderCompatJellyBean.newAccessibilityNodeProviderBridge( 50 new AccessibilityNodeProviderCompatJellyBean.AccessibilityNodeInfoBridge() { 51 @Override 52 public boolean performAction(int virtualViewId, int action, 53 Bundle arguments) { 54 return compat.performAction(virtualViewId, action, arguments); 55 } 56 57 @Override 58 public List<Object> findAccessibilityNodeInfosByText( 59 String text, int virtualViewId) { 60 final List<AccessibilityNodeInfoCompat> compatInfos = 61 compat.findAccessibilityNodeInfosByText(text, virtualViewId); 62 if (compatInfos == null) { 63 return null; 64 } else { 65 final List<Object> infos = new ArrayList<>(); 66 final int infoCount = compatInfos.size(); 67 for (int i = 0; i < infoCount; i++) { 68 AccessibilityNodeInfoCompat infoCompat = compatInfos.get(i); 69 infos.add(infoCompat.getInfo()); 70 } 71 return infos; 72 } 73 } 74 75 @Override 76 public Object createAccessibilityNodeInfo( 77 int virtualViewId) { 78 final AccessibilityNodeInfoCompat compatInfo = 79 compat.createAccessibilityNodeInfo(virtualViewId); 80 if (compatInfo == null) { 81 return null; 82 } else { 83 return compatInfo.getInfo(); 84 } 85 } 86 }); 87 } 88 } 89 90 private static class AccessibilityNodeProviderKitKatImpl 91 extends AccessibilityNodeProviderStubImpl { 92 @Override 93 public Object newAccessibilityNodeProviderBridge( 94 final AccessibilityNodeProviderCompat compat) { 95 return AccessibilityNodeProviderCompatKitKat.newAccessibilityNodeProviderBridge( 96 new AccessibilityNodeProviderCompatKitKat.AccessibilityNodeInfoBridge() { 97 @Override 98 public boolean performAction( 99 int virtualViewId, int action, Bundle arguments) { 100 return compat.performAction(virtualViewId, action, arguments); 101 } 102 103 @Override 104 public List<Object> findAccessibilityNodeInfosByText( 105 String text, int virtualViewId) { 106 final List<AccessibilityNodeInfoCompat> compatInfos = 107 compat.findAccessibilityNodeInfosByText(text, virtualViewId); 108 if (compatInfos == null) { 109 return null; 110 } else { 111 final List<Object> infos = new ArrayList<>(); 112 final int infoCount = compatInfos.size(); 113 for (int i = 0; i < infoCount; i++) { 114 AccessibilityNodeInfoCompat infoCompat = compatInfos.get(i); 115 infos.add(infoCompat.getInfo()); 116 } 117 return infos; 118 } 119 } 120 121 @Override 122 public Object createAccessibilityNodeInfo(int virtualViewId) { 123 final AccessibilityNodeInfoCompat compatInfo = 124 compat.createAccessibilityNodeInfo(virtualViewId); 125 if (compatInfo == null) { 126 return null; 127 } else { 128 return compatInfo.getInfo(); 129 } 130 } 131 132 @Override 133 public Object findFocus(int focus) { 134 final AccessibilityNodeInfoCompat compatInfo = compat.findFocus(focus); 135 if (compatInfo == null) { 136 return null; 137 } else { 138 return compatInfo.getInfo(); 139 } 140 } 141 }); 142 } 143 } 144 145 /** 146 * The virtual id for the hosting View. 147 */ 148 public static final int HOST_VIEW_ID = -1; 149 150 private static final AccessibilityNodeProviderImpl IMPL; 151 152 private final Object mProvider; 153 154 static { 155 if (Build.VERSION.SDK_INT >= 19) { // KitKat 156 IMPL = new AccessibilityNodeProviderKitKatImpl(); 157 } else if (Build.VERSION.SDK_INT >= 16) { // JellyBean 158 IMPL = new AccessibilityNodeProviderJellyBeanImpl(); 159 } else { 160 IMPL = new AccessibilityNodeProviderStubImpl(); 161 } 162 } 163 164 /** 165 * Creates a new instance. 166 */ 167 public AccessibilityNodeProviderCompat() { 168 mProvider = IMPL.newAccessibilityNodeProviderBridge(this); 169 } 170 171 /** 172 * Creates a new instance wrapping an 173 * {@link android.view.accessibility.AccessibilityNodeProvider}. 174 * 175 * @param provider The provider. 176 */ 177 public AccessibilityNodeProviderCompat(Object provider) { 178 mProvider = provider; 179 } 180 181 /** 182 * @return The wrapped {@link android.view.accessibility.AccessibilityNodeProvider}. 183 */ 184 public Object getProvider() { 185 return mProvider; 186 } 187 188 /** 189 * Returns an {@link AccessibilityNodeInfoCompat} representing a virtual view, 190 * i.e. a descendant of the host View, with the given <code>virtualViewId</code> 191 * or the host View itself if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 192 * <p> 193 * A virtual descendant is an imaginary View that is reported as a part of the view 194 * hierarchy for accessibility purposes. This enables custom views that draw complex 195 * content to report them selves as a tree of virtual views, thus conveying their 196 * logical structure. 197 * </p> 198 * <p> 199 * The implementer is responsible for obtaining an accessibility node info from the 200 * pool of reusable instances and setting the desired properties of the node info 201 * before returning it. 202 * </p> 203 * 204 * @param virtualViewId A client defined virtual view id. 205 * @return A populated {@link AccessibilityNodeInfoCompat} for a virtual descendant 206 * or the host View. 207 * 208 * @see AccessibilityNodeInfoCompat 209 */ 210 @Nullable 211 public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) { 212 return null; 213 } 214 215 /** 216 * Performs an accessibility action on a virtual view, i.e. a descendant of the 217 * host View, with the given <code>virtualViewId</code> or the host View itself 218 * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 219 * 220 * @param virtualViewId A client defined virtual view id. 221 * @param action The action to perform. 222 * @param arguments Optional arguments. 223 * @return True if the action was performed. 224 * 225 * @see #createAccessibilityNodeInfo(int) 226 * @see AccessibilityNodeInfoCompat 227 */ 228 public boolean performAction(int virtualViewId, int action, Bundle arguments) { 229 return false; 230 } 231 232 /** 233 * Finds {@link AccessibilityNodeInfoCompat}s by text. The match is case insensitive 234 * containment. The search is relative to the virtual view, i.e. a descendant of the 235 * host View, with the given <code>virtualViewId</code> or the host View itself 236 * <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}. 237 * 238 * @param virtualViewId A client defined virtual view id which defined 239 * the root of the tree in which to perform the search. 240 * @param text The searched text. 241 * @return A list of node info. 242 * 243 * @see #createAccessibilityNodeInfo(int) 244 * @see AccessibilityNodeInfoCompat 245 */ 246 @Nullable 247 public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text, 248 int virtualViewId) { 249 return null; 250 } 251 252 /** 253 * Find the virtual view, i.e. a descendant of the host View, that has the 254 * specified focus type. 255 * 256 * @param focus The focus to find. One of 257 * {@link AccessibilityNodeInfoCompat#FOCUS_INPUT} or 258 * {@link AccessibilityNodeInfoCompat#FOCUS_ACCESSIBILITY}. 259 * @return The node info of the focused view or null. 260 * @see AccessibilityNodeInfoCompat#FOCUS_INPUT 261 * @see AccessibilityNodeInfoCompat#FOCUS_ACCESSIBILITY 262 */ 263 @Nullable 264 public AccessibilityNodeInfoCompat findFocus(int focus) { 265 return null; 266 } 267 } 268