Add onFocus and onBlur to Pressable. (#30405)

Summary:
Starting to upstream keyboard-related features from React Native Windows - this is the Android implementation.
Exposing onFocus and onBlur callbacks on Pressable; they're already declared for View in ViewPropTypes.js, which Pressable wraps.

Registering event listeners in ReactViewManager to listen for native focus events.
## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[Android] [Added] - Add onFocus/onBlur for Pressable on Android.

Pull Request resolved: https://github.com/facebook/react-native/pull/30405

Test Plan:
Tested on v63-stable, since building master on Windows is now broken. Screenshots from RNTester running on the emulator:
![image](https://user-images.githubusercontent.com/12816515/99320373-59777e80-2820-11eb-91a8-704fff4aa13d.png)
![image](https://user-images.githubusercontent.com/12816515/99320412-6f853f00-2820-11eb-98f2-f9cd29e8aa0d.png)

Reviewed By: mdvacca

Differential Revision: D25444566

Pulled By: appden

fbshipit-source-id: ce0efd3e3b199a508df0ba1ce484b4de17471432
This commit is contained in:
Igor Klemenski
2021-01-08 13:59:48 -08:00
committed by Facebook GitHub Bot
parent 47bb3be6ce
commit cab4da7288
9 changed files with 131 additions and 16 deletions
@@ -1,4 +1,4 @@
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "rn_android_library")
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library")
rn_android_library(
name = "common",
@@ -18,5 +18,8 @@ rn_android_library(
"PUBLIC",
],
deps = [
react_native_target("java/com/facebook/react/uimanager:uimanager"),
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
react_native_target("java/com/facebook/react/bridge:bridge"),
],
)
@@ -5,19 +5,19 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.textinput;
package com.facebook.react.views.common;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
/** Event emitted by EditText native view when it loses focus. */
/* package */ class ReactTextInputBlurEvent extends Event<ReactTextInputBlurEvent> {
/** Event emitted by a native view when it loses focus. */
public class ReactViewBlurEvent extends Event<ReactViewBlurEvent> {
private static final String EVENT_NAME = "topBlur";
public ReactTextInputBlurEvent(int viewId) {
public ReactViewBlurEvent(int viewId) {
super(viewId);
}
@@ -5,19 +5,19 @@
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.views.textinput;
package com.facebook.react.views.common;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
/** Event emitted by EditText native view when it receives focus. */
/* package */ class ReactTextInputFocusEvent extends Event<ReactTextInputFocusEvent> {
/** Event emitted by a native view when it receives focus. */
public class ReactViewFocusEvent extends Event<ReactViewFocusEvent> {
private static final String EVENT_NAME = "topFocus";
public ReactTextInputFocusEvent(int viewId) {
public ReactViewFocusEvent(int viewId) {
super(viewId);
}
@@ -21,6 +21,7 @@ rn_android_library(
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
react_native_target("java/com/facebook/react/uimanager/annotations:annotations"),
react_native_target("java/com/facebook/react/views/common:common"),
react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"),
react_native_target("java/com/facebook/react/views/scroll:scroll"),
react_native_target("java/com/facebook/react/views/text:text"),
@@ -59,6 +59,8 @@ import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.common.ReactViewBlurEvent;
import com.facebook.react.views.common.ReactViewFocusEvent;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import com.facebook.react.views.scroll.ScrollEvent;
import com.facebook.react.views.scroll.ScrollEventType;
@@ -974,9 +976,9 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
public void onFocusChange(View v, boolean hasFocus) {
EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText);
if (hasFocus) {
eventDispatcher.dispatchEvent(new ReactTextInputFocusEvent(editText.getId()));
eventDispatcher.dispatchEvent(new ReactViewFocusEvent(editText.getId()));
} else {
eventDispatcher.dispatchEvent(new ReactTextInputBlurEvent(editText.getId()));
eventDispatcher.dispatchEvent(new ReactViewBlurEvent(editText.getId()));
eventDispatcher.dispatchEvent(
new ReactTextInputEndEditingEvent(
@@ -29,6 +29,8 @@ import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.annotations.ReactPropGroup;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.common.ReactViewBlurEvent;
import com.facebook.react.views.common.ReactViewFocusEvent;
import com.facebook.yoga.YogaConstants;
import java.util.Locale;
import java.util.Map;
@@ -234,8 +236,7 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
@Override
public void onClick(View v) {
final EventDispatcher mEventDispatcher =
UIManagerHelper.getEventDispatcherForReactTag(
(ReactContext) view.getContext(), view.getId());
getEventDispatcher((ReactContext) view.getContext(), view);
if (mEventDispatcher == null) {
return;
}
@@ -254,6 +255,27 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
}
}
private static EventDispatcher getEventDispatcher(
ReactContext reactContext, ReactViewGroup view) {
return UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId());
}
@Override
protected void addEventEmitters(
final ThemedReactContext reactContext, final ReactViewGroup view) {
view.setOnFocusChangeListener(
new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
EventDispatcher eventDispatcher = getEventDispatcher(reactContext, view);
if (hasFocus) {
eventDispatcher.dispatchEvent(new ReactViewFocusEvent(view.getId()));
} else {
eventDispatcher.dispatchEvent(new ReactViewBlurEvent(view.getId()));
}
}
});
}
@ReactProp(name = ViewProps.OVERFLOW)
public void setOverflow(ReactViewGroup view, String overflow) {
view.setOverflow(overflow);