java.lang.Object
↳androidx.core.view.AccessibilityDelegateCompat
Subclasses:
RecyclerViewAccessibilityDelegate, RecyclerViewAccessibilityDelegate.ItemDelegate, PreferenceRecyclerViewAccessibilityDelegate, ExploreByTouchHelper
Gradle dependencies
compile group: 'androidx.core', name: 'core', version: '1.9.0-alpha04'
- groupId: androidx.core
- artifactId: core
- version: 1.9.0-alpha04
Artifact androidx.core:core:1.9.0-alpha04 it located at Google repository (https://maven.google.com/)
Androidx artifact mapping:
androidx.core:core com.android.support:support-compat
Androidx class mapping:
androidx.core.view.AccessibilityDelegateCompat android.support.v4.view.AccessibilityDelegateCompat
Overview
Helper for accessing .
Note: On platform versions prior to
, delegate methods on
views in the android.widget.* package are called before
host methods. This prevents certain properties such as class name from
being modified by overriding
AccessibilityDelegateCompat.onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat),
as any changes will be overwritten by the host class.
Starting in , delegate
methods are called after host methods, which all properties to be
modified without being overwritten by the host class.
Summary
Methods |
---|
public boolean | dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)
Dispatches an to the host View first and then
to its children for adding their text content to the event. |
public AccessibilityNodeProviderCompat | getAccessibilityNodeProvider(View host)
Gets the provider for managing a virtual view hierarchy rooted at this View
and reported to s
that explore the window content. |
public void | onInitializeAccessibilityEvent(View host, AccessibilityEvent event)
Initializes an with information about the
the host View which is the event source. |
public void | onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info)
Initializes an AccessibilityNodeInfoCompat with information about the host view. |
public void | onPopulateAccessibilityEvent(View host, AccessibilityEvent event)
Gives a chance to the host View to populate the accessibility event with its
text content. |
public boolean | onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)
Called when a child of the host View has requested sending an
and gives an opportunity to the parent (the host)
to augment the event. |
public boolean | performAccessibilityAction(View host, int action, Bundle args)
Performs the specified accessibility action on the view. |
public void | sendAccessibilityEvent(View host, int eventType)
Sends an accessibility event of the given type. |
public void | sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)
Sends an accessibility event. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructors
public
AccessibilityDelegateCompat()
Creates a new instance.
public
AccessibilityDelegateCompat(AccessibilityDelegate originalDelegate)
Methods
public void
sendAccessibilityEvent(View host, int eventType)
Sends an accessibility event of the given type. If accessibility is not
enabled this method has no effect.
The default implementation behaves as View#sendAccessibilityEvent(int)
for the case of no accessibility delegate
been set.
Parameters:
host: The View hosting the delegate.
eventType: The type of the event to send.
See also: View#sendAccessibilityEvent(int)
public void
sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)
Sends an accessibility event. This method behaves exactly as
AccessibilityDelegateCompat.sendAccessibilityEvent(View, int) but takes as an argument an
empty and does not perform a check whether
accessibility is enabled.
The default implementation behaves as
View#sendAccessibilityEventUnchecked(AccessibilityEvent)
for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
event: The event to send.
See also: View#sendAccessibilityEventUnchecked(AccessibilityEvent)
public boolean
dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)
Dispatches an to the host View
first and then
to its children for adding their text content to the event.
The default implementation behaves as
View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
event: The event.
Returns:
True if the event population was completed.
See also: View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
public void
onPopulateAccessibilityEvent(View host, AccessibilityEvent event)
Gives a chance to the host View to populate the accessibility event with its
text content.
The default implementation behaves as
ViewCompat#onPopulateAccessibilityEvent(AccessibilityEvent) for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
event: The accessibility event which to populate.
See also: ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent)
public void
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)
Initializes an with information about the
the host View which is the event source.
The default implementation behaves as
ViewCompat#onInitalizeAccessibilityEvent(View v, AccessibilityEvent event) for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
event: The event to initialize.
See also: ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)
Initializes an AccessibilityNodeInfoCompat with information about the host view.
The default implementation behaves as
ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat) for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
info: The instance to initialize.
See also: ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
public boolean
onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)
Called when a child of the host View has requested sending an
and gives an opportunity to the parent (the host)
to augment the event.
The default implementation behaves as
ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent) for
the case of no accessibility delegate been set.
Parameters:
host: The View hosting the delegate.
child: The child which requests sending the event.
event: The event to be sent.
Returns:
True if the event should be sent
See also: ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
Gets the provider for managing a virtual view hierarchy rooted at this View
and reported to s
that explore the window content.
The default implementation behaves as
ViewCompat#getAccessibilityNodeProvider(View)
for the case of no accessibility delegate been set.
Returns:
The provider.
See also: AccessibilityNodeProviderCompat
public boolean
performAccessibilityAction(View host, int action, Bundle args)
Performs the specified accessibility action on the view. For
possible accessibility actions look at AccessibilityNodeInfoCompat.
The default implementation behaves as
View#performAccessibilityAction(int, Bundle)
for the case of
no accessibility delegate been set.
Parameters:
host: View on which to perform the action.
action: The action to perform.
args: Optional action arguments.
Returns:
Whether the action was performed.
See also: View#performAccessibilityAction(int, Bundle)
Source
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.core.view;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
import android.accessibilityservice.AccessibilityService;
import android.os.Build;
import android.os.Bundle;
import android.text.style.ClickableSpan;
import android.util.SparseArray;
import android.view.View;
import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.core.R;
import androidx.core.view.accessibility.AccessibilityClickableSpanCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import androidx.core.view.accessibility.AccessibilityNodeProviderCompat;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List;
/**
* Helper for accessing {@link AccessibilityDelegate}.
* <p>
* <strong>Note:</strong> On platform versions prior to
* {@link Build.VERSION_CODES#M API 23}, delegate methods on
* views in the {@code android.widget.*} package are called <i>before</i>
* host methods. This prevents certain properties such as class name from
* being modified by overriding
* {@link AccessibilityDelegateCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)},
* as any changes will be overwritten by the host class.
* <p>
* Starting in {@link Build.VERSION_CODES#M API 23}, delegate
* methods are called <i>after</i> host methods, which all properties to be
* modified without being overwritten by the host class.
*/
public class AccessibilityDelegateCompat {
static final class AccessibilityDelegateAdapter extends AccessibilityDelegate {
final AccessibilityDelegateCompat mCompat;
AccessibilityDelegateAdapter(AccessibilityDelegateCompat compat) {
mCompat = compat;
}
@Override
public boolean dispatchPopulateAccessibilityEvent(View host,
AccessibilityEvent event) {
return mCompat.dispatchPopulateAccessibilityEvent(host, event);
}
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
mCompat.onInitializeAccessibilityEvent(host, event);
}
@Override
public void onInitializeAccessibilityNodeInfo(
View host, AccessibilityNodeInfo info) {
AccessibilityNodeInfoCompat nodeInfoCompat = AccessibilityNodeInfoCompat.wrap(info);
nodeInfoCompat.setScreenReaderFocusable(ViewCompat.isScreenReaderFocusable(host));
nodeInfoCompat.setHeading(ViewCompat.isAccessibilityHeading(host));
nodeInfoCompat.setPaneTitle(ViewCompat.getAccessibilityPaneTitle(host));
nodeInfoCompat.setStateDescription(ViewCompat.getStateDescription(host));
mCompat.onInitializeAccessibilityNodeInfo(host, nodeInfoCompat);
nodeInfoCompat.addSpansToExtras(info.getText(), host);
List<AccessibilityActionCompat> actions = getActionList(host);
for (int i = 0; i < actions.size(); i++) {
nodeInfoCompat.addAction(actions.get(i));
}
}
@Override
public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
mCompat.onPopulateAccessibilityEvent(host, event);
}
@Override
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
AccessibilityEvent event) {
return mCompat.onRequestSendAccessibilityEvent(host, child, event);
}
@Override
public void sendAccessibilityEvent(View host, int eventType) {
mCompat.sendAccessibilityEvent(host, eventType);
}
@Override
public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
mCompat.sendAccessibilityEventUnchecked(host, event);
}
@Override
@RequiresApi(16)
public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
AccessibilityNodeProviderCompat provider =
mCompat.getAccessibilityNodeProvider(host);
return (provider != null)
? (AccessibilityNodeProvider) provider.getProvider() : null;
}
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
return mCompat.performAccessibilityAction(host, action, args);
}
}
private static final AccessibilityDelegate DEFAULT_DELEGATE = new AccessibilityDelegate();
private final AccessibilityDelegate mOriginalDelegate;
private final AccessibilityDelegate mBridge;
/**
* Creates a new instance.
*/
public AccessibilityDelegateCompat() {
this(DEFAULT_DELEGATE);
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
public AccessibilityDelegateCompat(@NonNull AccessibilityDelegate originalDelegate) {
mOriginalDelegate = originalDelegate;
mBridge = new AccessibilityDelegateAdapter(this);
}
/**
* @return The wrapped bridge implementation.
*/
AccessibilityDelegate getBridge() {
return mBridge;
}
/**
* Sends an accessibility event of the given type. If accessibility is not
* enabled this method has no effect.
* <p>
* The default implementation behaves as {@link View#sendAccessibilityEvent(int)
* View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
* been set.
* </p>
*
* @param host The View hosting the delegate.
* @param eventType The type of the event to send.
*
* @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
*/
public void sendAccessibilityEvent(@NonNull View host, int eventType) {
mOriginalDelegate.sendAccessibilityEvent(host, eventType);
}
/**
* Sends an accessibility event. This method behaves exactly as
* {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
* empty {@link AccessibilityEvent} and does not perform a check whether
* accessibility is enabled.
* <p>
* The default implementation behaves as
* {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
* View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param event The event to send.
*
* @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
* View#sendAccessibilityEventUnchecked(AccessibilityEvent)
*/
public void sendAccessibilityEventUnchecked(@NonNull View host,
@NonNull AccessibilityEvent event) {
mOriginalDelegate.sendAccessibilityEventUnchecked(host, event);
}
/**
* Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
* to its children for adding their text content to the event.
* <p>
* The default implementation behaves as
* {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
* View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param event The event.
* @return True if the event population was completed.
*
* @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
* View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
*/
public boolean dispatchPopulateAccessibilityEvent(@NonNull View host,
@NonNull AccessibilityEvent event) {
return mOriginalDelegate.dispatchPopulateAccessibilityEvent(host, event);
}
/**
* Gives a chance to the host View to populate the accessibility event with its
* text content.
* <p>
* The default implementation behaves as
* {@link ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent)
* ViewCompat#onPopulateAccessibilityEvent(AccessibilityEvent)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param event The accessibility event which to populate.
*
* @see ViewCompat#onPopulateAccessibilityEvent(View ,AccessibilityEvent)
* ViewCompat#onPopulateAccessibilityEvent(View, AccessibilityEvent)
*/
public void onPopulateAccessibilityEvent(@NonNull View host,
@NonNull AccessibilityEvent event) {
mOriginalDelegate.onPopulateAccessibilityEvent(host, event);
}
/**
* Initializes an {@link AccessibilityEvent} with information about the
* the host View which is the event source.
* <p>
* The default implementation behaves as
* {@link ViewCompat#onInitializeAccessibilityEvent(View v, AccessibilityEvent event)
* ViewCompat#onInitalizeAccessibilityEvent(View v, AccessibilityEvent event)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param event The event to initialize.
*
* @see ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)
* ViewCompat#onInitializeAccessibilityEvent(View, AccessibilityEvent)
*/
public void onInitializeAccessibilityEvent(@NonNull View host,
@NonNull AccessibilityEvent event) {
mOriginalDelegate.onInitializeAccessibilityEvent(host, event);
}
/**
* Initializes an {@link AccessibilityNodeInfoCompat} with information about the host view.
* <p>
* The default implementation behaves as
* {@link ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
* ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param info The instance to initialize.
*
* @see ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
* ViewCompat#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfoCompat)
*/
public void onInitializeAccessibilityNodeInfo(@NonNull View host,
@NonNull AccessibilityNodeInfoCompat info) {
mOriginalDelegate.onInitializeAccessibilityNodeInfo(
host, info.unwrap());
}
/**
* Called when a child of the host View has requested sending an
* {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
* to augment the event.
* <p>
* The default implementation behaves as
* {@link ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
* ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)} for
* the case of no accessibility delegate been set.
* </p>
*
* @param host The View hosting the delegate.
* @param child The child which requests sending the event.
* @param event The event to be sent.
* @return True if the event should be sent
*
* @see ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
* ViewGroupCompat#onRequestSendAccessibilityEvent(ViewGroup, View, AccessibilityEvent)
*/
public boolean onRequestSendAccessibilityEvent(@NonNull ViewGroup host, @NonNull View child,
@NonNull AccessibilityEvent event) {
return mOriginalDelegate.onRequestSendAccessibilityEvent(host, child, event);
}
/**
* Gets the provider for managing a virtual view hierarchy rooted at this View
* and reported to {@link AccessibilityService}s
* that explore the window content.
* <p>
* The default implementation behaves as
* {@link ViewCompat#getAccessibilityNodeProvider(View) ViewCompat#getAccessibilityNodeProvider(View)}
* for the case of no accessibility delegate been set.
* </p>
*
* @return The provider.
*
* @see AccessibilityNodeProviderCompat
*/
@Nullable
public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(@NonNull View host) {
if (Build.VERSION.SDK_INT >= 16) {
Object provider = Api16Impl.getAccessibilityNodeProvider(mOriginalDelegate, host);
if (provider != null) {
return new AccessibilityNodeProviderCompat(provider);
}
}
return null;
}
/**
* Performs the specified accessibility action on the view. For
* possible accessibility actions look at {@link AccessibilityNodeInfoCompat}.
* <p>
* The default implementation behaves as
* {@link View#performAccessibilityAction(int, Bundle)
* View#performAccessibilityAction(int, Bundle)} for the case of
* no accessibility delegate been set.
* </p>
*
*
* @param host View on which to perform the action.
* @param action The action to perform.
* @param args Optional action arguments.
* @return Whether the action was performed.
*
* @see View#performAccessibilityAction(int, Bundle)
* View#performAccessibilityAction(int, Bundle)
*/
public boolean performAccessibilityAction(@NonNull View host, int action,
@Nullable Bundle args) {
boolean success = false;
List<AccessibilityActionCompat> actions = getActionList(host);
for (int i = 0; i < actions.size(); i++) {
AccessibilityActionCompat actionCompat = actions.get(i);
if (actionCompat.getId() == action) {
success = actionCompat.perform(host, args);
break;
}
}
if (!success && Build.VERSION.SDK_INT >= 16) {
success = Api16Impl.performAccessibilityAction(mOriginalDelegate, host, action, args);
}
if (!success && action == R.id.accessibility_action_clickable_span && args != null) {
success = performClickableSpanAction(
args.getInt(AccessibilityClickableSpanCompat.SPAN_ID, -1), host);
}
return success;
}
@SuppressWarnings("unchecked")
private boolean performClickableSpanAction(int clickableSpanId, View host) {
SparseArray<WeakReference<ClickableSpan>> spans =
(SparseArray<WeakReference<ClickableSpan>>)
host.getTag(R.id.tag_accessibility_clickable_spans);
if (spans != null) {
WeakReference<ClickableSpan> reference = spans.get(clickableSpanId);
if (reference != null) {
ClickableSpan span = reference.get();
if (isSpanStillValid(span, host)) {
span.onClick(host);
return true;
}
}
}
return false;
}
private boolean isSpanStillValid(ClickableSpan span, View view) {
if (span != null) {
AccessibilityNodeInfo info = view.createAccessibilityNodeInfo();
ClickableSpan[] spans = AccessibilityNodeInfoCompat.getClickableSpans(info.getText());
for (int i = 0; spans != null && i < spans.length; i++) {
if (span.equals(spans[i])) {
return true;
}
}
}
return false;
}
@SuppressWarnings("unchecked")
static List<AccessibilityActionCompat> getActionList(View view) {
List<AccessibilityActionCompat> actions = (List<AccessibilityActionCompat>)
view.getTag(R.id.tag_accessibility_actions);
return actions == null ? Collections.emptyList() : actions;
}
@RequiresApi(16)
static class Api16Impl {
private Api16Impl() {
// This class is not instantiable.
}
@DoNotInline
static AccessibilityNodeProvider getAccessibilityNodeProvider(
AccessibilityDelegate accessibilityDelegate, View host) {
return accessibilityDelegate.getAccessibilityNodeProvider(host);
}
@DoNotInline
static boolean performAccessibilityAction(AccessibilityDelegate accessibilityDelegate,
View host, int action, Bundle args) {
return accessibilityDelegate.performAccessibilityAction(host, action, args);
}
}
}