Skip to content

Commit

Permalink
Added OnClick capabilities to touchable components for accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
sweggersen committed Apr 2, 2019
1 parent a2285b1 commit f733da5
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Libraries/Components/Touchable/TouchableBounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ const TouchableBounce = ((createReactClass({
nativeID={this.props.nativeID}
testID={this.props.testID}
hitSlop={this.props.hitSlop}
clickable={this.props.clickable !== false && this.props.onPress !== undefined && !this.props.disabled}
onClick={this.touchableHandlePress}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={
this.touchableHandleResponderTerminationRequest
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Components/Touchable/TouchableHighlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,8 @@ const TouchableHighlight = ((createReactClass({
nextFocusLeft={this.props.nextFocusLeft}
nextFocusRight={this.props.nextFocusRight}
nextFocusUp={this.props.nextFocusUp}
clickable={this.props.clickable !== false && this.props.onPress !== undefined}
onClick={this.touchableHandlePress}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={
this.touchableHandleResponderTerminationRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ const TouchableNativeFeedback = createReactClass({
nextFocusRight: this.props.nextFocusRight,
nextFocusUp: this.props.nextFocusUp,
hasTVPreferredFocus: this.props.hasTVPreferredFocus,
clickable: this.props.clickable !== false && this.props.onPress !== undefined && !this.props.disabled,
onClick: this.touchableHandlePress,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
onResponderTerminationRequest: this
.touchableHandleResponderTerminationRequest,
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Components/Touchable/TouchableOpacity.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ const TouchableOpacity = ((createReactClass({
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
tvParallaxProperties={this.props.tvParallaxProperties}
hitSlop={this.props.hitSlop}
clickable={this.props.clickable !== false && this.props.onPress !== undefined}
onClick={this.touchableHandlePress}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={
this.touchableHandleResponderTerminationRequest
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Components/Touchable/TouchableWithoutFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ const TouchableWithoutFeedback = ((createReactClass({
return (React: any).cloneElement(child, {
...overrides,
accessible: this.props.accessible !== false,
clickable: this.props.clickable !== false && this.props.onPress !== undefined,
onClick: this.touchableHandlePress,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
onResponderTerminationRequest: this
.touchableHandleResponderTerminationRequest,
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {TVViewProps} from 'TVViewPropTypes';
import type {
AccessibilityComponentType,
AccessibilityTrait,
AccessibilityNodeInfoProp,
AccessibilityRole,
AccessibilityStates,
} from 'ViewAccessibility';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
private static final String PROP_ELEVATION = "elevation";
private static final String PROP_Z_INDEX = "zIndex";
private static final String PROP_RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid";
private static final String PROP_ACCESSIBLE = "accessible";
private static final String PROP_ACCESSIBILITY_LABEL = "accessibilityLabel";
private static final String PROP_ACCESSIBILITY_COMPONENT_TYPE = "accessibilityComponentType";
private static final String PROP_ACCESSIBILITY_HINT = "accessibilityHint";
Expand Down Expand Up @@ -112,6 +113,11 @@ public void setNativeId(@Nonnull T view, String nativeId) {
ReactFindViewUtil.notifyViewRendered(view);
}

@ReactProp(name = PROP_ACCESSIBLE)
public void setAccessible(T view, boolean accessible) {
view.setImportantForAccessibility(accessible ? View.IMPORTANT_FOR_ACCESSIBILITY_YES : View.IMPORTANT_FOR_ACCESSIBILITY_NO);
}

@ReactProp(name = PROP_ACCESSIBILITY_LABEL)
public void setAccessibilityLabel(@Nonnull T view, String accessibilityLabel) {
view.setContentDescription(accessibilityLabel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
.put("topLoadingStart", MapBuilder.of(rn, "onLoadingStart"))
.put("topSelectionChange", MapBuilder.of(rn, "onSelectionChange"))
.put("topMessage", MapBuilder.of(rn, "onMessage"))
.put("topClick", MapBuilder.of(rn, "onClick"))
// Scroll events are added as per task T22348735.
// Subject for further improvement.
.put("topScrollBeginDrag", MapBuilder.of(rn, "onScrollBeginDrag"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import android.os.Build;
import android.view.View;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
Expand All @@ -21,10 +22,12 @@
import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.Spacing;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.ViewGroupManager;
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.yoga.YogaConstants;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -223,6 +226,29 @@ public void setCollapsable(ReactViewGroup view, boolean collapsable) {
// handled in NativeViewHierarchyOptimizer
}

@ReactProp(name = "clickable")
public void setClickable(final ReactViewGroup view, boolean clickable) {
if (clickable) {
view.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
final EventDispatcher mEventDispatcher = ((ReactContext)view.getContext()).getNativeModule(UIManagerModule.class)
.getEventDispatcher();
mEventDispatcher.dispatchEvent(new ViewGroupClickEvent(view.getId()));
}});

// Clickable elements are focusable. On API 26, this is taken care by setClickable.
// Explicitly calling setFocusable here for backward compatibility.
view.setFocusable(true /*isFocusable*/);
}
else {
view.setOnClickListener(null);
view.setClickable(false);
view.setFocusable(false);
}
}

@ReactProp(name = ViewProps.OVERFLOW)
public void setOverflow(ReactViewGroup view, String overflow) {
view.setOverflow(overflow);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.facebook.react.views.view;


import com.facebook.react.bridge.Arguments;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;

/**
* Represents a Click on the ReactViewGroup
*/
public class ViewGroupClickEvent extends Event<ViewGroupClickEvent> {
private static final String EVENT_NAME = "topClick";

public ViewGroupClickEvent(int viewId) {
super(viewId);
}

@Override
public String getEventName() {
return EVENT_NAME;
}

@Override
public boolean canCoalesce() {
return false;
}

@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), Arguments.createMap());
}
}

0 comments on commit f733da5

Please sign in to comment.