diff --git a/lib/java/com/google/android/material/textfield/DropdownMenuEndIconDelegate.java b/lib/java/com/google/android/material/textfield/DropdownMenuEndIconDelegate.java index 6d2633ed7ba..f255ebbd245 100644 --- a/lib/java/com/google/android/material/textfield/DropdownMenuEndIconDelegate.java +++ b/lib/java/com/google/android/material/textfield/DropdownMenuEndIconDelegate.java @@ -47,7 +47,6 @@ import androidx.core.view.ViewCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.google.android.material.animation.AnimationUtils; -import com.google.android.material.textfield.TextInputLayout.AccessibilityDelegate; import com.google.android.material.textfield.TextInputLayout.BoxBackgroundMode; /** Default initialization of the exposed dropdown menu {@link TextInputLayout.EndIconMode}. */ @@ -62,37 +61,6 @@ class DropdownMenuEndIconDelegate extends EndIconDelegate { @Nullable private AutoCompleteTextView autoCompleteTextView; - private final TextInputLayout.AccessibilityDelegate accessibilityDelegate = - new AccessibilityDelegate(textInputLayout) { - @Override - public void onInitializeAccessibilityNodeInfo( - View host, @NonNull AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(host, info); - // The non-editable exposed dropdown menu behaves like a Spinner. - if (!isEditable(autoCompleteTextView)) { - info.setClassName(Spinner.class.getName()); - } - if (info.isShowingHintText()) { - // Set hint text to null so TalkBack doesn't announce the label twice when there is no - // item selected. - info.setHintText(null); - } - } - - @Override - public void onPopulateAccessibilityEvent(View host, @NonNull AccessibilityEvent event) { - super.onPopulateAccessibilityEvent(host, event); - // If dropdown is non editable, layout click is what triggers showing/hiding the popup - // list. Otherwise, arrow icon alone is what triggers it. - if (event.getEventType() == TYPE_VIEW_CLICKED - && accessibilityManager.isEnabled() - && !isEditable(autoCompleteTextView)) { - showHideDropdown(); - updateDropdownPopupDirty(); - } - } - }; - private final OnClickListener onIconClickListener = view -> showHideDropdown(); private final OnFocusChangeListener onEditTextFocusChangeListener = (view, hasFocus) -> { @@ -177,8 +145,6 @@ public void onEditTextAttached(@Nullable EditText editText) { if (!isEditable(editText) && accessibilityManager.isTouchExplorationEnabled()) { ViewCompat.setImportantForAccessibility(endIconView, IMPORTANT_FOR_ACCESSIBILITY_NO); } - textInputLayout.setTextInputAccessibilityDelegate(accessibilityDelegate); - textInputLayout.setEndIconVisible(true); } @@ -202,6 +168,32 @@ OnFocusChangeListener getOnEditTextFocusChangeListener() { return onEditTextFocusChangeListener; } + @Override + public void onInitializeAccessibilityNodeInfo( + View host, @NonNull AccessibilityNodeInfoCompat info) { + // The non-editable exposed dropdown menu behaves like a Spinner. + if (!isEditable(autoCompleteTextView)) { + info.setClassName(Spinner.class.getName()); + } + if (info.isShowingHintText()) { + // Set hint text to null so TalkBack doesn't announce the label twice when there is no + // item selected. + info.setHintText(null); + } + } + + @Override + public void onPopulateAccessibilityEvent(View host, @NonNull AccessibilityEvent event) { + // If dropdown is non editable, layout click is what triggers showing/hiding the popup + // list. Otherwise, arrow icon alone is what triggers it. + if (event.getEventType() == TYPE_VIEW_CLICKED + && accessibilityManager.isEnabled() + && !isEditable(autoCompleteTextView)) { + showHideDropdown(); + updateDropdownPopupDirty(); + } + } + private void showHideDropdown() { if (autoCompleteTextView == null) { return; diff --git a/lib/java/com/google/android/material/textfield/EndIconDelegate.java b/lib/java/com/google/android/material/textfield/EndIconDelegate.java index 56bca009eaf..13d647d252c 100644 --- a/lib/java/com/google/android/material/textfield/EndIconDelegate.java +++ b/lib/java/com/google/android/material/textfield/EndIconDelegate.java @@ -18,12 +18,15 @@ import android.content.Context; import android.text.Editable; +import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; +import android.view.accessibility.AccessibilityEvent; import android.widget.EditText; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import com.google.android.material.internal.CheckableImageButton; import com.google.android.material.textfield.TextInputLayout.BoxBackgroundMode; @@ -122,4 +125,17 @@ void beforeEditTextChanged(CharSequence s, int start, int count, int after) {} * @see android.text.TextWatcher#afterTextChanged(Editable) */ void afterEditTextChanged(Editable s) {} + + /** + * This method will be called when the associated {@link TextInputLayout} is initializing the + * accessibility node info. + */ + void onInitializeAccessibilityNodeInfo(View host, @NonNull AccessibilityNodeInfoCompat info) {} + + /** + * This method will be called when the associated {@link TextInputLayout} is populating a + * accessibility event. + */ + void onPopulateAccessibilityEvent(View host, @NonNull AccessibilityEvent event) {} } + diff --git a/lib/java/com/google/android/material/textfield/TextInputLayout.java b/lib/java/com/google/android/material/textfield/TextInputLayout.java index c60a3103f9f..7d70143b3e5 100644 --- a/lib/java/com/google/android/material/textfield/TextInputLayout.java +++ b/lib/java/com/google/android/material/textfield/TextInputLayout.java @@ -4239,6 +4239,15 @@ public void onInitializeAccessibilityNodeInfo( info.setLabelFor(helperTextView); } } + + layout.endLayout.getEndIconDelegate().onInitializeAccessibilityNodeInfo(host, info); + } + + @Override + public void onPopulateAccessibilityEvent( + @NonNull View host, @NonNull AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(host, event); + layout.endLayout.getEndIconDelegate().onPopulateAccessibilityEvent(host, event); } } }