From bf33b9e4e707ca810e239c7255d24fe7d8d737df Mon Sep 17 00:00:00 2001 From: connieshi Date: Tue, 4 Sep 2018 14:17:13 -0400 Subject: [PATCH] Override onInitializeAccessibilityNodeInfo to explicitly tell the AccessibilityInfoNode whether a chip is checkable or clickable. Avoid setting custom ExploreByTouchHelper as delegate in pre-N unless there's a close/trailing icon. This is necessary to workaround a Talkback bug. PiperOrigin-RevId: 211490101 --- .../google/android/material/chip/Chip.java | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/java/com/google/android/material/chip/Chip.java b/lib/java/com/google/android/material/chip/Chip.java index 86052caaa..5323c63ef 100644 --- a/lib/java/com/google/android/material/chip/Chip.java +++ b/lib/java/com/google/android/material/chip/Chip.java @@ -79,6 +79,7 @@ import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; @@ -193,9 +194,13 @@ public class Chip extends AppCompatCheckBox implements Delegate { ChipDrawable.createFromAttributes( context, attrs, defStyleAttr, R.style.Widget_MaterialComponents_Chip_Action); setChipDrawable(drawable); - touchHelper = new ChipTouchHelper(this); - ViewCompat.setAccessibilityDelegate(this, touchHelper); + touchHelper = new ChipTouchHelper(this); + if (VERSION.SDK_INT >= VERSION_CODES.N) { + ViewCompat.setAccessibilityDelegate(this, touchHelper); + } else { + updateAccessibilityDelegate(); + } initOutlineProvider(); // Set deferred values setChecked(deferredCheckedValue); @@ -218,6 +223,27 @@ public class Chip extends AppCompatCheckBox implements Delegate { setupTouchTargetDelegate(context, attrs, defStyleAttr); } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(Chip.class.getName()); + info.setCheckable(isCheckable()); + info.setClickable(isClickable()); + } + + // TODO: Due to a11y bug, avoid setting custom ExploreByTouchHelper as delegate + // unless there's a close/trailing icon. Revert this once bug is fixed. + private void updateAccessibilityDelegate() { + if (VERSION.SDK_INT >= VERSION_CODES.N) { + return; + } + if ((hasCloseIcon() && isCloseIconVisible())) { + ViewCompat.setAccessibilityDelegate(this, touchHelper); + } else { + ViewCompat.setAccessibilityDelegate(this, null); + } + } + private void setupTouchTargetDelegate(Context context, AttributeSet attrs, int defStyleAttr) { if (attrs == null) { return; @@ -1040,7 +1066,8 @@ public class Chip extends AppCompatCheckBox implements Delegate { @Override protected void onPopulateNodeForHost(AccessibilityNodeInfoCompat node) { - node.setCheckable(chipDrawable != null && chipDrawable.isCheckable()); + node.setCheckable(isCheckable()); + node.setClickable(isClickable()); node.setClassName(Chip.class.getName()); CharSequence chipText = getText(); if (VERSION.SDK_INT >= VERSION_CODES.M) { @@ -1369,15 +1396,14 @@ public class Chip extends AppCompatCheckBox implements Delegate { } public void setCloseIconVisible(@BoolRes int id) { - if (chipDrawable != null) { - chipDrawable.setCloseIconVisible(id); - } + setCloseIconVisible(getResources().getBoolean(id)); } public void setCloseIconVisible(boolean closeIconVisible) { if (chipDrawable != null) { chipDrawable.setCloseIconVisible(closeIconVisible); } + updateAccessibilityDelegate(); } /** @deprecated Use {@link Chip#setCloseIconVisible(int)} instead. */ @@ -1401,12 +1427,14 @@ public class Chip extends AppCompatCheckBox implements Delegate { if (chipDrawable != null) { chipDrawable.setCloseIconResource(id); } + updateAccessibilityDelegate(); } public void setCloseIcon(@Nullable Drawable closeIcon) { if (chipDrawable != null) { chipDrawable.setCloseIcon(closeIcon); } + updateAccessibilityDelegate(); } @Nullable