2020
2121import static com .google .android .material .theme .overlay .MaterialThemeOverlay .wrap ;
2222
23+ import android .accessibilityservice .AccessibilityServiceInfo ;
2324import android .content .Context ;
2425import android .content .res .ColorStateList ;
2526import android .content .res .TypedArray ;
3536import android .text .InputType ;
3637import android .util .AttributeSet ;
3738import android .view .View ;
39+ import android .view .View .MeasureSpec ;
3840import android .view .ViewGroup ;
3941import android .view .ViewGroup .LayoutParams ;
4042import android .view .ViewParent ;
5860import com .google .android .material .internal .ThemeEnforcement ;
5961import com .google .android .material .resources .MaterialResources ;
6062import com .google .android .material .shape .MaterialShapeDrawable ;
63+ import java .util .List ;
6164
6265/**
6366 * A special sub-class of {@link android.widget.AutoCompleteTextView} that is auto-inflated so that
7376public class MaterialAutoCompleteTextView extends AppCompatAutoCompleteTextView {
7477
7578 private static final int MAX_ITEMS_MEASURED = 15 ;
79+ private static final String SWITCH_ACCESS_ACTIVITY_NAME = "SwitchAccess" ;
7680
7781 @ NonNull private final ListPopupWindow modalListPopup ;
7882 @ Nullable private final AccessibilityManager accessibilityManager ;
@@ -185,7 +189,7 @@ public void onItemClick(AdapterView<?> parent, View selectedView, int position,
185189
186190 @ Override
187191 public void showDropDown () {
188- if (isTouchExplorationEnabled ()) {
192+ if (isPopupRequired ()) {
189193 modalListPopup .show ();
190194 } else {
191195 super .showDropDown ();
@@ -194,7 +198,7 @@ public void showDropDown() {
194198
195199 @ Override
196200 public void dismissDropDown () {
197- if (isTouchExplorationEnabled ()) {
201+ if (isPopupRequired ()) {
198202 modalListPopup .dismiss ();
199203 } else {
200204 super .dismissDropDown ();
@@ -203,18 +207,40 @@ public void dismissDropDown() {
203207
204208 @ Override
205209 public void onWindowFocusChanged (boolean hasWindowFocus ) {
206- if (isTouchExplorationEnabled ()) {
207- // Do not dismissDropDown if touch exploration is enabled, in case the window lost focus
208- // in favor of the modalListPopup.
210+ if (isPopupRequired ()) {
211+ // Do not dismissDropDown if touch exploration or switch access is enabled, in case the window
212+ // lost focus in favor of the modalListPopup.
209213 return ;
210214 }
211215 super .onWindowFocusChanged (hasWindowFocus );
212216 }
213217
218+ private boolean isPopupRequired () {
219+ return isTouchExplorationEnabled () || isSwitchAccessEnabled ();
220+ }
221+
214222 private boolean isTouchExplorationEnabled () {
215223 return accessibilityManager != null && accessibilityManager .isTouchExplorationEnabled ();
216224 }
217225
226+ private boolean isSwitchAccessEnabled () {
227+ if (accessibilityManager == null || !accessibilityManager .isEnabled ()) {
228+ return false ;
229+ }
230+ List <AccessibilityServiceInfo > accessibilityServiceInfos =
231+ accessibilityManager .getEnabledAccessibilityServiceList (
232+ AccessibilityServiceInfo .FEEDBACK_GENERIC );
233+ if (accessibilityServiceInfos != null ) {
234+ for (AccessibilityServiceInfo info : accessibilityServiceInfos ) {
235+ if (info .getSettingsActivityName () != null
236+ && info .getSettingsActivityName ().contains (SWITCH_ACCESS_ACTIVITY_NAME )) {
237+ return true ;
238+ }
239+ }
240+ }
241+ return false ;
242+ }
243+
218244 @ Override
219245 public <T extends ListAdapter & Filterable > void setAdapter (@ Nullable T adapter ) {
220246 super .setAdapter (adapter );
0 commit comments