Fabric: Support of accessibility events for <View> component

Summary: This also illustrates how we should use EventHandlers objects.

Reviewed By: fkgozali

Differential Revision: D8053357

fbshipit-source-id: cba084c8a871e40c7536720fce290c3467d33061
This commit is contained in:
Valentin Shergin 2018-05-22 15:48:24 -07:00 committed by Facebook Github Bot
parent 1064dad9bf
commit 20645681d1
8 changed files with 111 additions and 15 deletions

View File

@ -9,8 +9,10 @@
#import <React/RCTComponentViewProtocol.h> #import <React/RCTComponentViewProtocol.h>
#import <React/UIView+ComponentViewProtocol.h> #import <React/UIView+ComponentViewProtocol.h>
#import <fabric/core/EventHandlers.h>
#import <fabric/core/LayoutMetrics.h> #import <fabric/core/LayoutMetrics.h>
#import <fabric/core/Props.h> #import <fabric/core/Props.h>
#import <fabric/view/ViewEventHandlers.h>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@ -21,6 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
@protected @protected
facebook::react::LayoutMetrics _layoutMetrics; facebook::react::LayoutMetrics _layoutMetrics;
facebook::react::SharedProps _props; facebook::react::SharedProps _props;
facebook::react::SharedViewEventHandlers _eventHandlers;
} }
@end @end

View File

@ -8,13 +8,15 @@
#import "RCTViewComponentView.h" #import "RCTViewComponentView.h"
#import <fabric/view/ViewProps.h> #import <fabric/view/ViewProps.h>
#import <fabric/view/ViewEventHandlers.h>
using namespace facebook::react; using namespace facebook::react;
@implementation RCTViewComponentView @implementation RCTViewComponentView
- (void)updateProps:(facebook::react::SharedProps)props - (void)updateProps:(SharedProps)props
oldProps:(facebook::react::SharedProps)oldProps oldProps:(SharedProps)oldProps
{ {
if (!oldProps) { if (!oldProps) {
oldProps = _props ?: std::make_shared<ViewProps>(); oldProps = _props ?: std::make_shared<ViewProps>();
@ -31,6 +33,12 @@ using namespace facebook::react;
// TODO: Implement all sutable non-layout <View> props. // TODO: Implement all sutable non-layout <View> props.
} }
- (void)updateEventHandlers:(SharedEventHandlers)eventHandlers
{
assert(std::dynamic_pointer_cast<const ViewEventHandlers>(eventHandlers));
_eventHandlers = std::static_pointer_cast<const ViewEventHandlers>(eventHandlers);
}
- (void)updateLayoutMetrics:(LayoutMetrics)layoutMetrics - (void)updateLayoutMetrics:(LayoutMetrics)layoutMetrics
oldLayoutMetrics:(LayoutMetrics)oldLayoutMetrics oldLayoutMetrics:(LayoutMetrics)oldLayoutMetrics
{ {
@ -39,4 +47,24 @@ using namespace facebook::react;
_layoutMetrics = layoutMetrics; _layoutMetrics = layoutMetrics;
} }
#pragma mark - Accessibility Events
- (BOOL)accessibilityActivate
{
_eventHandlers->onAccessibilityTap();
return YES;
}
- (BOOL)accessibilityPerformMagicTap
{
_eventHandlers->onAccessibilityMagicTap();
return YES;
}
- (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)action
{
_eventHandlers->onAccessibilityAction([action.name cStringUsingEncoding:NSASCIIStringEncoding]);
return YES;
}
@end @end

View File

@ -17,11 +17,13 @@ namespace react {
/* /*
* Descriptor for <Paragraph> component. * Descriptor for <Paragraph> component.
*/ */
class ParagraphComponentDescriptor: public ConcreteComponentDescriptor<ParagraphShadowNode> { class ParagraphComponentDescriptor final:
public ConcreteComponentDescriptor<ParagraphShadowNode> {
public: public:
ParagraphComponentDescriptor(): ParagraphComponentDescriptor(SharedEventDispatcher eventDispatcher):
ConcreteComponentDescriptor<ParagraphShadowNode>() { ConcreteComponentDescriptor<ParagraphShadowNode>(eventDispatcher) {
// Every single `ParagraphShadowNode` will have a reference to // Every single `ParagraphShadowNode` will have a reference to
// a shared `TextLayoutManager`. // a shared `TextLayoutManager`.
textLayoutManager_ = std::make_shared<TextLayoutManager>(); textLayoutManager_ = std::make_shared<TextLayoutManager>();

View File

@ -12,6 +12,7 @@
#include <fabric/core/ShadowNode.h> #include <fabric/core/ShadowNode.h>
#include <fabric/debug/DebugStringConvertibleItem.h> #include <fabric/debug/DebugStringConvertibleItem.h>
#include <fabric/view/AccessibleShadowNode.h> #include <fabric/view/AccessibleShadowNode.h>
#include <fabric/view/ViewEventHandlers.h>
#include <fabric/view/ViewProps.h> #include <fabric/view/ViewProps.h>
#include <fabric/view/YogaLayoutableShadowNode.h> #include <fabric/view/YogaLayoutableShadowNode.h>
@ -23,9 +24,9 @@ namespace react {
* as <View> and similar basic behaviour). * as <View> and similar basic behaviour).
* For example: <Paragraph>, <Image>, but not <Text>, <RawText>. * For example: <Paragraph>, <Image>, but not <Text>, <RawText>.
*/ */
template <typename ViewPropsT> template <typename ViewPropsT = ViewProps, typename ViewEventHandlersT = ViewEventHandlers>
class ConcreteViewShadowNode: class ConcreteViewShadowNode:
public ConcreteShadowNode<ViewPropsT>, public ConcreteShadowNode<ViewPropsT, ViewEventHandlersT>,
public AccessibleShadowNode, public AccessibleShadowNode,
public YogaLayoutableShadowNode { public YogaLayoutableShadowNode {
@ -37,21 +38,23 @@ public:
using ConcreteViewProps = ViewPropsT; using ConcreteViewProps = ViewPropsT;
using SharedConcreteViewProps = std::shared_ptr<const ViewPropsT>; using SharedConcreteViewProps = std::shared_ptr<const ViewPropsT>;
using ConcreteViewEventHandlers = ViewEventHandlersT;
using SharedConcreteViewEventHandlers = std::shared_ptr<const ViewEventHandlersT>;
using SharedConcreteViewShadowNode = std::shared_ptr<const ConcreteViewShadowNode>; using SharedConcreteViewShadowNode = std::shared_ptr<const ConcreteViewShadowNode>;
ConcreteViewShadowNode( ConcreteViewShadowNode(
const Tag &tag, const Tag &tag,
const Tag &rootTag, const Tag &rootTag,
const InstanceHandle &instanceHandle,
const SharedConcreteViewProps &props, const SharedConcreteViewProps &props,
const SharedConcreteViewEventHandlers &eventHandlers,
const SharedShadowNodeSharedList &children, const SharedShadowNodeSharedList &children,
const ShadowNodeCloneFunction &cloneFunction const ShadowNodeCloneFunction &cloneFunction
): ):
ConcreteShadowNode<ViewPropsT>( ConcreteShadowNode<ViewPropsT, ViewEventHandlersT>(
tag, tag,
rootTag, rootTag,
instanceHandle,
props, props,
eventHandlers,
children, children,
cloneFunction cloneFunction
), ),
@ -66,11 +69,13 @@ public:
ConcreteViewShadowNode( ConcreteViewShadowNode(
const SharedConcreteViewShadowNode &shadowNode, const SharedConcreteViewShadowNode &shadowNode,
const SharedConcreteViewProps &props, const SharedConcreteViewProps &props,
const SharedConcreteViewEventHandlers &eventHandlers,
const SharedShadowNodeSharedList &children const SharedShadowNodeSharedList &children
): ):
ConcreteShadowNode<ViewPropsT>( ConcreteShadowNode<ViewPropsT, ViewEventHandlersT>(
shadowNode, shadowNode,
props, props,
eventHandlers,
children children
), ),
AccessibleShadowNode( AccessibleShadowNode(

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ViewEventHandlers.h"
namespace facebook {
namespace react {
#pragma mark - Accessibility
void ViewEventHandlers::onAccessibilityAction(const std::string &name) const {
dispatchEvent("accessibilityAction", folly::dynamic::object("action", name));
}
void ViewEventHandlers::onAccessibilityTap() const {
dispatchEvent("accessibilityTap");
}
void ViewEventHandlers::onAccessibilityMagicTap() const {
dispatchEvent("magicTap");
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <memory>
#include <fabric/core/EventHandlers.h>
namespace facebook {
namespace react {
class ViewEventHandlers;
using SharedViewEventHandlers = std::shared_ptr<const ViewEventHandlers>;
class ViewEventHandlers:
public EventHandlers {
public:
using EventHandlers::EventHandlers;
void onAccessibilityAction(const std::string &name) const;
void onAccessibilityTap() const;
void onAccessibilityMagicTap() const;
};
} // namespace react
} // namespace facebook

View File

@ -20,7 +20,7 @@ class ViewShadowNode;
using SharedViewShadowNode = std::shared_ptr<const ViewShadowNode>; using SharedViewShadowNode = std::shared_ptr<const ViewShadowNode>;
class ViewShadowNode final: class ViewShadowNode final:
public ConcreteViewShadowNode<ViewProps> { public ConcreteViewShadowNode<ViewProps, ViewEventHandlers> {
public: public:

View File

@ -35,9 +35,6 @@ public:
const AccessibilityTraits accessibilityTraits {AccessibilityTraits::None}; const AccessibilityTraits accessibilityTraits {AccessibilityTraits::None};
const bool accessibilityViewIsModal {false}; const bool accessibilityViewIsModal {false};
const bool accessibilityElementsHidden {false}; const bool accessibilityElementsHidden {false};
const SharedDirectEventHandler onAccessibilityAction {nullptr};
const SharedDirectEventHandler onAccessibilityTap {nullptr};
const SharedDirectEventHandler onMagicTap {nullptr};
}; };
} // namespace react } // namespace react