From ee7c702308cbf1a2a1509be51c9c5fd263a85f36 Mon Sep 17 00:00:00 2001 From: Doug Russell Date: Thu, 6 Dec 2018 19:39:42 -0800 Subject: [PATCH] Accessibility Escape Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/22047 Differential Revision: D13146179 Pulled By: cpojer fbshipit-source-id: b8a089114a5deafee47dd482e484d413c8c39137 --- Libraries/Components/View/ReactNativeViewAttributes.js | 1 + Libraries/Components/View/ViewPropTypes.js | 8 ++++++++ RNTester/js/AccessibilityIOSExample.js | 5 +++++ .../ComponentViews/View/RCTViewComponentView.mm | 6 ++++++ React/Views/RCTView.h | 1 + React/Views/RCTView.m | 10 ++++++++++ React/Views/RCTViewManager.m | 1 + .../fabric/components/view/ViewEventEmitter.cpp | 4 ++++ ReactCommon/fabric/components/view/ViewEventEmitter.h | 1 + 9 files changed, 37 insertions(+) diff --git a/Libraries/Components/View/ReactNativeViewAttributes.js b/Libraries/Components/View/ReactNativeViewAttributes.js index 5b4ab1c6c..3ab651c37 100644 --- a/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/Libraries/Components/View/ReactNativeViewAttributes.js @@ -34,6 +34,7 @@ ReactNativeViewAttributes.UIView = { onAccessibilityAction: true, onAccessibilityTap: true, onMagicTap: true, + onAccessibilityEscape: true, collapsable: true, needsOffscreenAlphaCompositing: true, style: ReactNativeStyleAttributes, diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index a5f54867c..f1e5cbe79 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -62,6 +62,14 @@ type DirectEventProps = $ReadOnly<{| * See http://facebook.github.io/react-native/docs/view.html#onmagictap */ onMagicTap?: ?() => void, + + /** + * When `accessible` is `true`, the system will invoke this function when the + * user performs the escape gesture. + * + * See http://facebook.github.io/react-native/docs/view.html#onaccessibilityescape + */ + onAccessibilityEscape?: ?Function, |}>; type TouchEventProps = $ReadOnly<{| diff --git a/RNTester/js/AccessibilityIOSExample.js b/RNTester/js/AccessibilityIOSExample.js index 96ed8fc39..d6e20efc8 100644 --- a/RNTester/js/AccessibilityIOSExample.js +++ b/RNTester/js/AccessibilityIOSExample.js @@ -30,6 +30,11 @@ class AccessibilityIOSExample extends React.Component<{}> { accessible={true}> Accessibility magic tap example + alert('onAccessibilityEscape success')} + accessible={true}> + Accessibility escape example + Accessibility label example diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index d9e3884c1..82ae59c11 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -553,6 +553,12 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view) return YES; } +- (BOOL)accessibilityPerformEscape +{ + _eventEmitter->onAccessibilityEscape(); + return YES; +} + - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)action { _eventEmitter->onAccessibilityAction(RCTStringFromNSString(action.name)); diff --git a/React/Views/RCTView.h b/React/Views/RCTView.h index 65ba3bfd6..a4ef2b3e0 100644 --- a/React/Views/RCTView.h +++ b/React/Views/RCTView.h @@ -24,6 +24,7 @@ @property (nonatomic, copy) RCTDirectEventBlock onAccessibilityAction; @property (nonatomic, copy) RCTDirectEventBlock onAccessibilityTap; @property (nonatomic, copy) RCTDirectEventBlock onMagicTap; +@property (nonatomic, copy) RCTDirectEventBlock onAccessibilityEscape; /** * Accessibility properties diff --git a/React/Views/RCTView.m b/React/Views/RCTView.m index f8091b906..1493bbed0 100644 --- a/React/Views/RCTView.m +++ b/React/Views/RCTView.m @@ -284,6 +284,16 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused) } } +- (BOOL)accessibilityPerformEscape +{ + if (_onAccessibilityEscape) { + _onAccessibilityEscape(nil); + return YES; + } else { + return NO; + } +} + - (NSString *)description { NSString *superDescription = super.description; diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index 154e9b0a2..2eee1a65c 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -119,6 +119,7 @@ RCT_REMAP_VIEW_PROPERTY(accessibilityIgnoresInvertColors, reactAccessibilityElem RCT_REMAP_VIEW_PROPERTY(onAccessibilityAction, reactAccessibilityElement.onAccessibilityAction, RCTDirectEventBlock) RCT_REMAP_VIEW_PROPERTY(onAccessibilityTap, reactAccessibilityElement.onAccessibilityTap, RCTDirectEventBlock) RCT_REMAP_VIEW_PROPERTY(onMagicTap, reactAccessibilityElement.onMagicTap, RCTDirectEventBlock) +RCT_REMAP_VIEW_PROPERTY(onAccessibilityEscape, reactAccessibilityElement.onAccessibilityEscape, RCTDirectEventBlock) RCT_REMAP_VIEW_PROPERTY(testID, reactAccessibilityElement.accessibilityIdentifier, NSString) RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor) diff --git a/ReactCommon/fabric/components/view/ViewEventEmitter.cpp b/ReactCommon/fabric/components/view/ViewEventEmitter.cpp index ccd839874..4ab1f9002 100644 --- a/ReactCommon/fabric/components/view/ViewEventEmitter.cpp +++ b/ReactCommon/fabric/components/view/ViewEventEmitter.cpp @@ -28,6 +28,10 @@ void ViewEventEmitter::onAccessibilityMagicTap() const { dispatchEvent("magicTap"); } +void ViewEventEmitter::onAccessibilityEscape() const { + dispatchEvent("accessibilityEscape"); +} + #pragma mark - Layout void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const { diff --git a/ReactCommon/fabric/components/view/ViewEventEmitter.h b/ReactCommon/fabric/components/view/ViewEventEmitter.h index 431ede000..e16b4f98c 100644 --- a/ReactCommon/fabric/components/view/ViewEventEmitter.h +++ b/ReactCommon/fabric/components/view/ViewEventEmitter.h @@ -28,6 +28,7 @@ class ViewEventEmitter : public TouchEventEmitter { void onAccessibilityAction(const std::string &name) const; void onAccessibilityTap() const; void onAccessibilityMagicTap() const; + void onAccessibilityEscape() const; #pragma mark - Layout