From bed5c5997cea201bc0e28d77c232d2a33973285e Mon Sep 17 00:00:00 2001 From: pfthomas Date: Tue, 5 Apr 2022 15:47:01 -0400 Subject: [PATCH] [BadgeDrawable][a11y] Attach/detach badge contentDescription when using menuItem. Resolves https://github.com/material-components/material-components-android/issues/2429 PiperOrigin-RevId: 439651014 (cherry picked from commit ee49c5aa8bed9b0c3a15421725b4f3164c3c6973) --- .../android/material/badge/BadgeUtils.java | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/java/com/google/android/material/badge/BadgeUtils.java b/lib/java/com/google/android/material/badge/BadgeUtils.java index bcdf89dcf9b..18431ba7c75 100644 --- a/lib/java/com/google/android/material/badge/BadgeUtils.java +++ b/lib/java/com/google/android/material/badge/BadgeUtils.java @@ -33,6 +33,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.google.android.material.internal.ParcelableSparseArray; import com.google.android.material.internal.ToolbarUtils; @@ -96,7 +99,6 @@ public static void attachBadgeDrawable( anchor.getOverlay().add(badgeDrawable); } } - } /** @@ -131,11 +133,39 @@ public void run() { if (menuItemView != null) { setToolbarOffset(badgeDrawable, toolbar.getResources()); BadgeUtils.attachBadgeDrawable(badgeDrawable, menuItemView, customBadgeParent); + attachBadgeContentDescription(badgeDrawable, menuItemView); } } }); } + private static void attachBadgeContentDescription( + @NonNull final BadgeDrawable badgeDrawable, @NonNull View view) { + if (VERSION.SDK_INT >= VERSION_CODES.Q && ViewCompat.hasAccessibilityDelegate(view)) { + ViewCompat.setAccessibilityDelegate( + view, + new AccessibilityDelegateCompat(view.getAccessibilityDelegate()) { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setContentDescription(badgeDrawable.getContentDescription()); + } + }); + } else { + ViewCompat.setAccessibilityDelegate( + view, + new AccessibilityDelegateCompat() { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setContentDescription(badgeDrawable.getContentDescription()); + } + }); + } + } + /** * Detaches a BadgeDrawable from its associated anchor. For API 18+, the BadgeDrawable will be * removed from its anchor's ViewOverlay. For pre-API 18, the BadgeDrawable will be removed from @@ -167,11 +197,29 @@ public static void detachBadgeDrawable( if (menuItemView != null) { removeToolbarOffset(badgeDrawable); detachBadgeDrawable(badgeDrawable, menuItemView); + detachBadgeContentDescription(menuItemView); } else { Log.w(LOG_TAG, "Trying to remove badge from a null menuItemView: " + menuItemId); } } + private static void detachBadgeContentDescription(@NonNull View view) { + if (VERSION.SDK_INT >= VERSION_CODES.Q && ViewCompat.hasAccessibilityDelegate(view)) { + ViewCompat.setAccessibilityDelegate( + view, + new AccessibilityDelegateCompat(view.getAccessibilityDelegate()) { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + info.setContentDescription(null); + } + }); + } else { + ViewCompat.setAccessibilityDelegate(view, null); + } + } + @VisibleForTesting static void setToolbarOffset(BadgeDrawable badgeDrawable, Resources resources) { badgeDrawable.setAdditionalHorizontalOffset(