@@ -2549,8 +2549,11 @@ public TextView getPrefixTextView() {
25492549 }
25502550
25512551 private void updatePrefixTextVisibility () {
2552- prefixTextView . setVisibility (( prefixText != null && !isHintExpanded ()) ? VISIBLE : GONE ) ;
2552+ int visibility = ( prefixText != null && !isHintExpanded ()) ? VISIBLE : GONE ;
25532553 updateStartLayoutVisibility ();
2554+ // Set visibility after updating start layout's visibility so screen readers correctly announce
2555+ // when prefix text appears.
2556+ prefixTextView .setVisibility (visibility );
25542557 updateDummyDrawables ();
25552558 }
25562559
@@ -2636,13 +2639,15 @@ public TextView getSuffixTextView() {
26362639 }
26372640
26382641 private void updateSuffixTextVisibility () {
2639- int oldSuffixVisibility = suffixTextView .getVisibility ();
2640- boolean visible = suffixText != null && !isHintExpanded ();
2641- suffixTextView .setVisibility (visible ? VISIBLE : GONE );
2642- if (oldSuffixVisibility != suffixTextView .getVisibility ()) {
2643- getEndIconDelegate ().onSuffixVisibilityChanged (visible );
2642+ int oldVisibility = suffixTextView .getVisibility ();
2643+ int newVisibility = (suffixText != null && !isHintExpanded ()) ? VISIBLE : GONE ;
2644+ if (oldVisibility != newVisibility ) {
2645+ getEndIconDelegate ().onSuffixVisibilityChanged (/* visible= */ newVisibility == VISIBLE );
26442646 }
26452647 updateEndLayoutVisibility ();
2648+ // Set visibility after updating end layout's visibility so screen readers correctly announce
2649+ // when suffix text appears.
2650+ suffixTextView .setVisibility (newVisibility );
26462651 updateDummyDrawables ();
26472652 }
26482653
@@ -3976,15 +3981,17 @@ private void updateEndLayoutVisibility() {
39763981 endIconFrame .setVisibility (
39773982 (endIconView .getVisibility () == VISIBLE && !isErrorIconVisible ()) ? VISIBLE : GONE );
39783983
3984+ int suffixTextVisibility = (suffixText != null && !isHintExpanded ()) ? VISIBLE : GONE ;
39793985 boolean shouldBeVisible =
3980- isEndIconVisible () || isErrorIconVisible () || suffixTextView . getVisibility () == VISIBLE ;
3986+ isEndIconVisible () || isErrorIconVisible () || suffixTextVisibility == VISIBLE ;
39813987 endLayout .setVisibility (shouldBeVisible ? VISIBLE : GONE );
39823988 }
39833989
39843990 private void updateStartLayoutVisibility () {
39853991 // Set startLayout to visible if start icon or prefix text is present.
3992+ int prefixTextVisibility = (prefixText != null && !isHintExpanded ()) ? VISIBLE : GONE ;
39863993 boolean shouldBeVisible =
3987- startIconView .getVisibility () == VISIBLE || prefixTextView . getVisibility () == VISIBLE ;
3994+ startIconView .getVisibility () == VISIBLE || prefixTextVisibility == VISIBLE ;
39883995 startLayout .setVisibility (shouldBeVisible ? VISIBLE : GONE );
39893996 }
39903997
@@ -4598,9 +4605,18 @@ public void onInitializeAccessibilityNodeInfo(
45984605 boolean isHintCollapsed = !layout .isHintExpanded ();
45994606 boolean showingError = !TextUtils .isEmpty (errorText );
46004607 boolean contentInvalid = showingError || !TextUtils .isEmpty (counterOverflowDesc );
4601-
4608+ boolean isShowingPrefixText = layout . getPrefixTextView (). getVisibility () == VISIBLE ;
46024609 String hint = hasHint ? hintText .toString () : "" ;
46034610
4611+ // Screen readers should follow visual order of the elements of the text field.
4612+ if (isShowingPrefixText ) {
4613+ info .setLabelFor (layout .getPrefixTextView ());
4614+ info .setTraversalAfter (layout .getPrefixTextView ());
4615+ } else {
4616+ info .setTraversalAfter (layout .startIconView );
4617+ }
4618+
4619+ // Make sure text field has the appropriate announcements.
46044620 if (showingText ) {
46054621 info .setText (inputText );
46064622 } else if (!TextUtils .isEmpty (hint )) {
0 commit comments