blob: f4c7b96b8edc81d8368bd2ff9906dc4f9e9926ff [file] [log] [blame]
Svetoslav Ganov02107852011-10-03 17:06:56 -07001/*
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.view.accessibility;
18
19import android.accessibilityservice.AccessibilityService;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070020import android.os.Bundle;
Svetoslav Ganov02107852011-10-03 17:06:56 -070021import android.view.View;
22
23import java.util.List;
24
25/**
26 * This class is the contract a client should implement to enable support of a
27 * virtual view hierarchy rooted at a given view for accessibility purposes. A virtual
28 * view hierarchy is a tree of imaginary Views that is reported as a part of the view
29 * hierarchy when an {@link AccessibilityService} explores the window content.
30 * Since the virtual View tree does not exist this class is responsible for
31 * managing the {@link AccessibilityNodeInfo}s describing that tree to accessibility
32 * services.
33 * </p>
34 * <p>
35 * The main use case of these APIs is to enable a custom view that draws complex content,
36 * for example a monthly calendar grid, to be presented as a tree of logical nodes,
37 * for example month days each containing events, thus conveying its logical structure.
38 * <p>
39 * <p>
40 * A typical use case is to override {@link View#getAccessibilityNodeProvider()} of the
41 * View that is a root of a virtual View hierarchy to return an instance of this class.
42 * In such a case this instance is responsible for managing {@link AccessibilityNodeInfo}s
43 * describing the virtual sub-tree rooted at the View including the one representing the
44 * View itself. Similarly the returned instance is responsible for performing accessibility
45 * actions on any virtual view or the root view itself. For example:
46 * </p>
Kevin Hufnaglee0d4d962019-08-24 01:04:09 +000047 * <div>
48 * <div class="ds-selector-tabs"><section><h3 id="kotlin">Kotlin</h3>
49 * <pre class="prettyprint lang-kotlin">
50 * // "view" is the View instance on which this class performs accessibility functions.
51 * class MyCalendarViewAccessibilityDelegate(
52 * private var view: MyCalendarView) : AccessibilityDelegate() {
53 * override fun getAccessibilityNodeProvider(host: View): AccessibilityNodeProvider {
54 * return object : AccessibilityNodeProvider() {
55 * override fun createAccessibilityNodeInfo(virtualViewId: Int):
56 * AccessibilityNodeInfo? {
57 * when (virtualViewId) {
58 * <var>host-view-id</var> -&gt; {
59 * val node = AccessibilityNodeInfo.obtain(view)
60 * node.addChild(view, <var>child-view-id</var>)
61 * // Set other attributes like screenReaderFocusable
62 * // and contentDescription.
63 * return node
64 * }
65 * <var>child-view-id</var> -&gt; {
66 * val node = AccessibilityNodeInfo
67 * .obtain(view, virtualViewId)
68 * node.setParent(view)
69 * node.addAction(ACTION_SCROLL_UP)
70 * node.addAction(ACTION_SCROLL_DOWN)
71 * // Set other attributes like focusable and visibleToUser.
72 * node.setBoundsInScreen(
73 * Rect(<var>coords-of-edges-relative-to-screen</var>))
74 * return node
75 * }
76 * else -&gt; return null
77 * }
78 * }
79 *
80 * override fun performAction(
81 * virtualViewId: Int,
82 * action: Int,
83 * arguments: Bundle
84 * ): Boolean {
85 * if (virtualViewId == <var>host-view-id</var>) {
86 * return view.performAccessibilityAction(action, arguments)
87 * }
88 * when (action) {
89 * ACTION_SCROLL_UP.id -&gt; {
90 * // Implement logic in a separate method.
91 * navigateToPreviousMonth()
92 *
93 * return true
94 * }
95 * ACTION_SCROLL_DOWN.id -&gt;
96 * // Implement logic in a separate method.
97 * navigateToNextMonth()
98 *
99 * return true
100 * else -&gt; return false
101 * }
102 * }
103 * }
104 * }
105 * }
106 * </pre>
107 * </section><section><h3 id="java">Java</h3>
108 * <pre class="prettyprint lang-java">
109 * final class MyCalendarViewAccessibilityDelegate extends AccessibilityDelegate {
110 * // The View instance on which this class performs accessibility functions.
111 * private final MyCalendarView view;
112 *
113 * MyCalendarViewAccessibilityDelegate(MyCalendarView view) {
114 * this.view = view;
115 * }
116 *
117 * &#64;Override
118 * public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
119 * return new AccessibilityNodeProvider() {
120 * &#64;Override
121 * &#64;Nullable
122 * public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
123 * if (virtualViewId == <var>host-view-id</var>) {
124 * AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(view);
125 * node.addChild(view, <var>child-view-id</var>);
126 * // Set other attributes like screenReaderFocusable and contentDescription.
127 * return node;
128 * } else if (virtualViewId == <var>child-view-id</var>) {
129 * AccessibilityNodeInfo node =
130 * AccessibilityNodeInfo.obtain(view, virtualViewId);
131 * node.setParent(view);
132 * node.addAction(ACTION_SCROLL_UP);
133 * node.addAction(ACTION_SCROLL_DOWN);
134 * // Set other attributes like focusable and visibleToUser.
135 * node.setBoundsInScreen(
136 * new Rect(<var>coordinates-of-edges-relative-to-screen</var>));
137 * return node;
138 * } else {
139 * return null;
140 * }
141 * }
142 *
143 * &#64;Override
144 * public boolean performAction(int virtualViewId, int action, Bundle arguments) {
145 * if (virtualViewId == <var>host-view-id</var>) {
146 * return view.performAccessibilityAction(action, arguments);
147 * }
148 *
149 * if (action == ACTION_SCROLL_UP.getId()) {
150 * // Implement logic in a separate method.
151 * navigateToPreviousMonth();
152 *
153 * return true;
154 * } else if (action == ACTION_SCROLL_DOWN.getId()) {
155 * // Implement logic in a separate method.
156 * navigateToNextMonth();
157 *
158 * return true;
159 * } else {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700160 * return false;
161 * }
Kevin Hufnaglee0d4d962019-08-24 01:04:09 +0000162 * }
163 * };
164 * }
165 * }
166 * </pre></section></div></div>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700167 */
168public abstract class AccessibilityNodeProvider {
169
170 /**
Svetoslav8e3feb12014-02-24 13:46:47 -0800171 * The virtual id for the hosting View.
172 */
173 public static final int HOST_VIEW_ID = -1;
174
175 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -0700176 * Returns an {@link AccessibilityNodeInfo} representing a virtual view,
Cindy Kuang12d37472017-08-09 10:08:15 -0700177 * such as a descendant of the host View, with the given <code>virtualViewId</code>
Svetoslav8e3feb12014-02-24 13:46:47 -0800178 * or the host View itself if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700179 * <p>
180 * A virtual descendant is an imaginary View that is reported as a part of the view
181 * hierarchy for accessibility purposes. This enables custom views that draw complex
182 * content to report them selves as a tree of virtual views, thus conveying their
183 * logical structure.
184 * </p>
185 * <p>
186 * The implementer is responsible for obtaining an accessibility node info from the
187 * pool of reusable instances and setting the desired properties of the node info
188 * before returning it.
189 * </p>
190 *
191 * @param virtualViewId A client defined virtual view id.
192 * @return A populated {@link AccessibilityNodeInfo} for a virtual descendant or the
193 * host View.
194 *
Svetoslav Ganov42138042012-03-20 11:51:39 -0700195 * @see View#createAccessibilityNodeInfo()
Svetoslav Ganov02107852011-10-03 17:06:56 -0700196 * @see AccessibilityNodeInfo
197 */
198 public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
199 return null;
200 }
201
202 /**
Phil Weaverc2e28932016-12-08 12:29:25 -0800203 * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
204 * additional data.
205 * <p>
206 * This method only needs to be implemented if a virtual view offers to provide additional
207 * data.
208 * </p>
209 *
210 * @param virtualViewId The virtual view id used to create the node
211 * @param info The info to which to add the extra data
212 * @param extraDataKey A key specifying the type of extra data to add to the info. The
213 * extra data should be added to the {@link Bundle} returned by
214 * the info's {@link AccessibilityNodeInfo#getExtras} method.
215 * @param arguments A {@link Bundle} holding any arguments relevant for this request.
216 *
Aurimas Liutikase701dc12018-06-01 16:04:37 -0700217 * @see AccessibilityNodeInfo#setAvailableExtraData(List)
Phil Weaverc2e28932016-12-08 12:29:25 -0800218 */
219 public void addExtraDataToAccessibilityNodeInfo(
220 int virtualViewId, AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
221 }
222
223 /**
Cindy Kuang12d37472017-08-09 10:08:15 -0700224 * Performs an accessibility action on a virtual view, such as a descendant of the
Svetoslav Ganov02107852011-10-03 17:06:56 -0700225 * host View, with the given <code>virtualViewId</code> or the host View itself
Svetoslav8e3feb12014-02-24 13:46:47 -0800226 * if <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700227 *
Svetoslav Ganov02107852011-10-03 17:06:56 -0700228 * @param virtualViewId A client defined virtual view id.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700229 * @param action The action to perform.
230 * @param arguments Optional action arguments.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700231 * @return True if the action was performed.
232 *
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700233 * @see View#performAccessibilityAction(int, Bundle)
Svetoslav Ganov02107852011-10-03 17:06:56 -0700234 * @see #createAccessibilityNodeInfo(int)
235 * @see AccessibilityNodeInfo
236 */
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700237 public boolean performAction(int virtualViewId, int action, Bundle arguments) {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700238 return false;
239 }
240
241 /**
242 * Finds {@link AccessibilityNodeInfo}s by text. The match is case insensitive
243 * containment. The search is relative to the virtual view, i.e. a descendant of the
Svetoslav8e3feb12014-02-24 13:46:47 -0800244 * host View, with the given <code>virtualViewId</code> or the host View itself
245 * <code>virtualViewId</code> equals to {@link #HOST_VIEW_ID}.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700246 *
247 * @param virtualViewId A client defined virtual view id which defined
248 * the root of the tree in which to perform the search.
249 * @param text The searched text.
250 * @return A list of node info.
251 *
252 * @see #createAccessibilityNodeInfo(int)
253 * @see AccessibilityNodeInfo
254 */
255 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text,
256 int virtualViewId) {
257 return null;
258 }
Alan Viverette2e1e0812013-09-30 13:45:55 -0700259
260 /**
Cindy Kuang12d37472017-08-09 10:08:15 -0700261 * Find the virtual view, such as a descendant of the host View, that has the
Alan Viverette2e1e0812013-09-30 13:45:55 -0700262 * specified focus type.
263 *
264 * @param focus The focus to find. One of
265 * {@link AccessibilityNodeInfo#FOCUS_INPUT} or
266 * {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
267 * @return The node info of the focused view or null.
268 * @see AccessibilityNodeInfo#FOCUS_INPUT
269 * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
270 */
271 public AccessibilityNodeInfo findFocus(int focus) {
272 return null;
273 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700274}