Add setNextFocus support (#22082)

Summary:
Add properties to be able to set the nextFocus. It can be very useful with Android TV.

New android View properties :

* nextFocusDown binded to [setNextFocusDownId](https://developer.android.com/reference/android/view/View.html#setNextFocusDownId(int))
* nextFocusForward binded to [setNextFocusForwardId](https://developer.android.com/reference/android/view/View.html#setNextFocusForwardId(int))
* nextFocusLeft binded to [setNextFocusLeftId](https://developer.android.com/reference/android/view/View.html#setNextFocusLeftId(int))
* nextFocusRight binded to [setNextFocusRightId](https://developer.android.com/reference/android/view/View.html#setNextFocusRightId(int))
* nextFocusUp binded to [setNextFocusUpId](https://developer.android.com/reference/android/view/View.html#setNextFocusUpId(int))

Can be used to fix :

* Fixes #20593
* Fixes #20100

Same PR as #22080 but accorded to changes on master
Pull Request resolved: https://github.com/facebook/react-native/pull/22082

Differential Revision: D14162740

Pulled By: cpojer

fbshipit-source-id: 9a13a185d4e8307ce67014fb076c62d135c487c3
This commit is contained in:
Grégoire Rit
2019-02-20 23:34:39 -08:00
committed by Facebook Github Bot
parent f8a4d281e2
commit c416b40542
6 changed files with 231 additions and 1 deletions

View File

@@ -43,6 +43,41 @@ type ButtonProps = $ReadOnly<{|
*/
hasTVPreferredFocus?: ?boolean,
/**
* TV next focus down (see documentation for the View component).
*
* @platform android
*/
nextFocusDown?: ?number,
/**
* TV next focus forward (see documentation for the View component).
*
* @platform android
*/
nextFocusForward?: ?number,
/**
* TV next focus left (see documentation for the View component).
*
* @platform android
*/
nextFocusLeft?: ?number,
/**
* TV next focus right (see documentation for the View component).
*
* @platform android
*/
nextFocusRight?: ?number,
/**
* TV next focus up (see documentation for the View component).
*
* @platform android
*/
nextFocusUp?: ?number,
/**
* Text to display for blindness accessibility features
*/
@@ -95,6 +130,11 @@ class Button extends React.Component<ButtonProps> {
onPress,
title,
hasTVPreferredFocus,
nextFocusDown,
nextFocusForward,
nextFocusLeft,
nextFocusRight,
nextFocusUp,
disabled,
testID,
} = this.props;
@@ -127,6 +167,11 @@ class Button extends React.Component<ButtonProps> {
accessibilityRole="button"
accessibilityStates={accessibilityStates}
hasTVPreferredFocus={hasTVPreferredFocus}
nextFocusDown={nextFocusDown}
nextFocusForward={nextFocusForward}
nextFocusLeft={nextFocusLeft}
nextFocusRight={nextFocusRight}
nextFocusUp={nextFocusUp}
testID={testID}
disabled={disabled}
onPress={onPress}>

View File

@@ -43,9 +43,18 @@ type IOSProps = $ReadOnly<{|
tvParallaxProperties?: ?TVParallaxPropertiesType,
|}>;
type AndroidProps = $ReadOnly<{|
nextFocusDown?: ?number,
nextFocusForward?: ?number,
nextFocusLeft?: ?number,
nextFocusRight?: ?number,
nextFocusUp?: ?number,
|}>;
type Props = $ReadOnly<{|
...TouchableWithoutFeedbackProps,
...IOSProps,
...AndroidProps,
activeOpacity?: ?number,
underlayColor?: ?ColorValue,
@@ -189,7 +198,48 @@ const TouchableHighlight = ((createReactClass({
*/
hasTVPreferredFocus: PropTypes.bool,
/**
* Apple TV parallax effects
* TV next focus down (see documentation for the View component).
*
* @platform android
*/
nextFocusDown: PropTypes.number,
/**
* TV next focus forward (see documentation for the View component).
*
* @platform android
*/
nextFocusForward: PropTypes.number,
/**
* TV next focus left (see documentation for the View component).
*
* @platform android
*/
nextFocusLeft: PropTypes.number,
/**
* TV next focus right (see documentation for the View component).
*
* @platform android
*/
nextFocusRight: PropTypes.number,
/**
* TV next focus up (see documentation for the View component).
*
* @platform android
*/
nextFocusUp: PropTypes.number,
/**
* *(Apple TV only)* Object with properties to control Apple TV parallax effects.
*
* enabled: If true, parallax effects are enabled. Defaults to true.
* shiftDistanceX: Defaults to 2.0.
* shiftDistanceY: Defaults to 2.0.
* tiltAngle: Defaults to 0.05.
* magnification: Defaults to 1.0.
* pressMagnification: Defaults to 1.0.
* pressDuration: Defaults to 0.3.
* pressDelay: Defaults to 0.0.
*
* @platform ios
*/
tvParallaxProperties: PropTypes.object,
/**
@@ -367,6 +417,11 @@ const TouchableHighlight = ((createReactClass({
isTVSelectable={true}
tvParallaxProperties={this.props.tvParallaxProperties}
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
nextFocusDown={this.props.nextFocusDown}
nextFocusForward={this.props.nextFocusForward}
nextFocusLeft={this.props.nextFocusLeft}
nextFocusRight={this.props.nextFocusRight}
nextFocusUp={this.props.nextFocusUp}
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
onResponderTerminationRequest={
this.touchableHandleResponderTerminationRequest

View File

@@ -93,6 +93,31 @@ const TouchableNativeFeedback = createReactClass({
*/
hasTVPreferredFocus: PropTypes.bool,
/**
* TV next focus down (see documentation for the View component).
*/
nextFocusDown: PropTypes.number,
/**
* TV next focus forward (see documentation for the View component).
*/
nextFocusForward: PropTypes.number,
/**
* TV next focus left (see documentation for the View component).
*/
nextFocusLeft: PropTypes.number,
/**
* TV next focus right (see documentation for the View component).
*/
nextFocusRight: PropTypes.number,
/**
* TV next focus up (see documentation for the View component).
*/
nextFocusUp: PropTypes.number,
/**
* Set to true to add the ripple effect to the foreground of the view, instead of the
* background. This is useful if one of your child views has a background of its own, or you're
@@ -303,6 +328,11 @@ const TouchableNativeFeedback = createReactClass({
onLayout: this.props.onLayout,
hitSlop: this.props.hitSlop,
isTVSelectable: true,
nextFocusDown: this.props.nextFocusDown,
nextFocusForward: this.props.nextFocusForward,
nextFocusLeft: this.props.nextFocusLeft,
nextFocusRight: this.props.nextFocusRight,
nextFocusUp: this.props.nextFocusUp,
hasTVPreferredFocus: this.props.hasTVPreferredFocus,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
onResponderTerminationRequest: this

View File

@@ -32,6 +32,11 @@ const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
type TVProps = $ReadOnly<{|
hasTVPreferredFocus?: ?boolean,
nextFocusDown?: ?number,
nextFocusForward?: ?number,
nextFocusLeft?: ?number,
nextFocusRight?: ?number,
nextFocusUp?: ?number,
tvParallaxProperties?: ?TVParallaxPropertiesType,
|}>;
@@ -148,6 +153,36 @@ const TouchableOpacity = ((createReactClass({
* TV preferred focus (see documentation for the View component).
*/
hasTVPreferredFocus: PropTypes.bool,
/**
* TV next focus down (see documentation for the View component).
*
* @platform android
*/
nextFocusDown: PropTypes.number,
/**
* TV next focus forward (see documentation for the View component).
*
* @platform android
*/
nextFocusForward: PropTypes.number,
/**
* TV next focus left (see documentation for the View component).
*
* @platform android
*/
nextFocusLeft: PropTypes.number,
/**
* TV next focus right (see documentation for the View component).
*
* @platform android
*/
nextFocusRight: PropTypes.number,
/**
* TV next focus up (see documentation for the View component).
*
* @platform android
*/
nextFocusUp: PropTypes.number,
/**
* Apple TV parallax effects
*/
@@ -281,6 +316,11 @@ const TouchableOpacity = ((createReactClass({
testID={this.props.testID}
onLayout={this.props.onLayout}
isTVSelectable={true}
nextFocusDown={this.props.nextFocusDown}
nextFocusForward={this.props.nextFocusForward}
nextFocusLeft={this.props.nextFocusLeft}
nextFocusRight={this.props.nextFocusRight}
nextFocusUp={this.props.nextFocusUp}
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
tvParallaxProperties={this.props.tvParallaxProperties}
hitSlop={this.props.hitSlop}

View File

@@ -284,6 +284,41 @@ type AndroidViewProps = $ReadOnly<{|
* See http://facebook.github.io/react-native/docs/view.html#importantforaccessibility
*/
importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'),
/**
* TV next focus down (see documentation for the View component).
*
* @platform android
*/
nextFocusDown?: ?number,
/**
* TV next focus forward (see documentation for the View component).
*
* @platform android
*/
nextFocusForward?: ?number,
/**
* TV next focus left (see documentation for the View component).
*
* @platform android
*/
nextFocusLeft?: ?number,
/**
* TV next focus right (see documentation for the View component).
*
* @platform android
*/
nextFocusRight?: ?number,
/**
* TV next focus up (see documentation for the View component).
*
* @platform android
*/
nextFocusUp?: ?number,
|}>;
type IOSViewProps = $ReadOnly<{|

View File

@@ -65,6 +65,31 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
}
}
@ReactProp(name = "nextFocusDown", defaultInt = View.NO_ID)
public void nextFocusDown(ReactViewGroup view, int viewId) {
view.setNextFocusDownId(viewId);
}
@ReactProp(name = "nextFocusForward", defaultInt = View.NO_ID)
public void nextFocusForward(ReactViewGroup view, int viewId) {
view.setNextFocusForwardId(viewId);
}
@ReactProp(name = "nextFocusLeft", defaultInt = View.NO_ID)
public void nextFocusLeft(ReactViewGroup view, int viewId) {
view.setNextFocusLeftId(viewId);
}
@ReactProp(name = "nextFocusRight", defaultInt = View.NO_ID)
public void nextFocusRight(ReactViewGroup view, int viewId) {
view.setNextFocusRightId(viewId);
}
@ReactProp(name = "nextFocusUp", defaultInt = View.NO_ID)
public void nextFocusUp(ReactViewGroup view, int viewId) {
view.setNextFocusUpId(viewId);
}
@ReactPropGroup(names = {
ViewProps.BORDER_RADIUS,
ViewProps.BORDER_TOP_LEFT_RADIUS,