diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 7f8137c9c4a..94f346ec40d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -12,6 +12,7 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; import android.text.Editable; import android.text.InputType; import android.text.SpannableStringBuilder; @@ -25,10 +26,13 @@ import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.ReactContext; import com.facebook.react.uimanager.UIManagerModule; @@ -60,8 +64,8 @@ public class ReactEditText extends EditText { // listeners and adding them back again after the text change is completed. protected boolean mIsSettingTextFromJS; // This component is controlled, so we want it to get focused only when JS ask it to do so. - // Whenever android requests focus (which it does for random reasons), it will be ignored. - private boolean mIsJSSettingFocus; + // Whenever android requests focus, except for accessibility click, it will be ignored. + private boolean mShouldAllowFocus; private int mDefaultGravityHorizontal; private int mDefaultGravityVertical; protected int mNativeEventCount; @@ -98,7 +102,7 @@ public class ReactEditText extends EditText { mNativeEventCount = 0; mMostRecentEventCount = 0; mIsSettingTextFromJS = false; - mIsJSSettingFocus = false; + mShouldAllowFocus = false; mBlurOnSubmit = null; mDisableFullscreen = false; mListeners = null; @@ -116,6 +120,19 @@ public class ReactEditText extends EditText { && Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } + + ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegateCompat() { + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == AccessibilityNodeInfo.ACTION_CLICK) { + mShouldAllowFocus = true; + requestFocus(); + mShouldAllowFocus = false; + return true; + } + return super.performAccessibilityAction(host, action, args); + } + }); } // After the text changes inside an EditText, TextView checks if a layout() has been requested. @@ -208,9 +225,11 @@ public class ReactEditText extends EditText { if (isFocused()) { return true; } - if (!mIsJSSettingFocus) { + + if (!mShouldAllowFocus) { return false; } + setFocusableInTouchMode(true); boolean focused = super.requestFocus(direction, previouslyFocusedRect); if (getShowSoftInputOnFocus()) { @@ -361,9 +380,9 @@ public class ReactEditText extends EditText { // VisibleForTesting from {@link TextInputEventsTestCase}. public void requestFocusFromJS() { - mIsJSSettingFocus = true; + mShouldAllowFocus = true; requestFocus(); - mIsJSSettingFocus = false; + mShouldAllowFocus = false; } /* package */ void clearFocusFromJS() {