From 8d3eeb0d3e2eb364fd6659d9f7a6b8c6b99aec8c Mon Sep 17 00:00:00 2001 From: James Ide Date: Mon, 6 Apr 2015 18:30:26 -0700 Subject: [PATCH] [Touchable] Expose the touch-retention offset as a prop The touch-retention offset defines a rect around a touchable component in which the touch is retained. Easiest way to see this is to touch a button in a real navigation bar and slide your finger out of the range and back in. This diff exposes the offset as a prop (I thought touchRetentionOffset was a more informative name than pressRectOffset) Fixes #198 --- .../Components/Touchable/TouchableBounce.js | 32 +++++++++++++------ .../Touchable/TouchableHighlight.js | 13 ++++++-- .../Components/Touchable/TouchableOpacity.js | 23 +++++++------ .../Touchable/TouchableWithoutFeedback.js | 31 ++++++++++++------ 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Libraries/Components/Touchable/TouchableBounce.js b/Libraries/Components/Touchable/TouchableBounce.js index 7cba2216472945..73525318aaea31 100644 --- a/Libraries/Components/Touchable/TouchableBounce.js +++ b/Libraries/Components/Touchable/TouchableBounce.js @@ -11,6 +11,7 @@ */ 'use strict'; +var EdgeInsetsPropType = require('EdgeInsetsPropType'); var NativeMethodsMixin = require('NativeMethodsMixin'); var React = require('React'); var POPAnimation = require('POPAnimation'); @@ -21,17 +22,16 @@ var merge = require('merge'); var copyProperties = require('copyProperties'); var onlyChild = require('onlyChild'); +var TOUCH_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; + +type DefaultProps = { + touchRetentionOffset: typeof TOUCH_RETENTION_OFFSET; +}; + type State = { animationID: ?number; }; -/** - * When the scroll view is disabled, this defines how far your touch may move - * off of the button, before deactivating the button. Once deactivated, try - * moving it back and you'll see that the button is once again reactivated! - * Move it back and forth several times while the scroll view is disabled. - */ -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; /** * Example of using the `TouchableMixin` to play well with other responder * locking views including `ScrollView`. `TouchableMixin` provides touchable @@ -50,6 +50,20 @@ var TouchableBounce = React.createClass({ onPressWithCompletion: React.PropTypes.func, // the function passed is called after the animation is complete onPressAnimationComplete: React.PropTypes.func, + /** + * When the scroll view is disabled, this defines how far your touch may + * move off of the button, before deactivating the button. Once deactivated, + * try moving it back and you'll see that the button is once again + * reactivated! Move it back and forth several times while the scroll view + * is disabled. Ensure you pass in a constant to reduce memory allocations. + */ + touchRetentionOffset: EdgeInsetsPropType.isRequired, + }, + + getDefaultProps: function(): DefaultProps { + return { + touchRetentionOffset: TOUCH_RETENTION_OFFSET, + }; }, getInitialState: function(): State { @@ -114,8 +128,8 @@ var TouchableBounce = React.createClass({ this.props.onPress && this.props.onPress(); }, - touchableGetPressRectOffset: function(): typeof PRESS_RECT_OFFSET { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! + touchableGetPressRectOffset: function(): typeof TOUCH_RETENTION_OFFSET { + return this.props.touchRetentionOffset; }, touchableGetHighlightDelayMS: function(): number { diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index 080a6750c2666b..83688f9495a21b 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -12,6 +12,7 @@ // Note (avik): add @flow when Flow supports spread properties in propTypes +var EdgeInsetsPropType = require('EdgeInsetsPropType'); var NativeMethodsMixin = require('NativeMethodsMixin'); var React = require('React'); var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); @@ -30,6 +31,7 @@ var onlyChild = require('onlyChild'); var DEFAULT_PROPS = { activeOpacity: 0.8, underlayColor: 'black', + touchRetentionOffset: {top: 20, left: 20, right: 20, bottom: 30}, }; /** @@ -69,6 +71,14 @@ var TouchableHighlight = React.createClass({ * active. */ underlayColor: React.PropTypes.string, + /** + * When the scroll view is disabled, this defines how far your touch may + * move off of the button, before deactivating the button. Once deactivated, + * try moving it back and you'll see that the button is once again + * reactivated! Move it back and forth several times while the scroll view + * is disabled. Ensure you pass in a constant to reduce memory allocations. + */ + touchRetentionOffset: EdgeInsetsPropType.isRequired, style: View.propTypes.style, }, @@ -153,7 +163,7 @@ var TouchableHighlight = React.createClass({ }, touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! + return this.props.touchRetentionOffset; }, _showUnderlay: function() { @@ -197,7 +207,6 @@ var TouchableHighlight = React.createClass({ } }); -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; var CHILD_REF = keyOf({childRef: null}); var UNDERLAY_REF = keyOf({underlayRef: null}); var INACTIVE_CHILD_PROPS = { diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index e590999debd23f..76aff8f404640c 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -12,6 +12,7 @@ // Note (avik): add @flow when Flow supports spread properties in propTypes +var EdgeInsetsPropType = require('EdgeInsetsPropType'); var NativeMethodsMixin = require('NativeMethodsMixin'); var POPAnimationMixin = require('POPAnimationMixin'); var React = require('React'); @@ -23,6 +24,8 @@ var ensureComponentIsNative = require('ensureComponentIsNative'); var keyOf = require('keyOf'); var onlyChild = require('onlyChild'); +var TOUCH_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; + /** * A wrapper for making views respond properly to touches. * On press down, the opacity of the wrapped view is decreased, dimming it. @@ -44,7 +47,6 @@ var onlyChild = require('onlyChild'); * }, * ``` */ - var TouchableOpacity = React.createClass({ mixins: [Touchable.Mixin, NativeMethodsMixin, POPAnimationMixin], @@ -55,11 +57,20 @@ var TouchableOpacity = React.createClass({ * active. */ activeOpacity: React.PropTypes.number, + /** + * When the scroll view is disabled, this defines how far your touch may + * move off of the button, before deactivating the button. Once deactivated, + * try moving it back and you'll see that the button is once again + * reactivated! Move it back and forth several times while the scroll view + * is disabled. Ensure you pass in a constant to reduce memory allocations. + */ + touchRetentionOffset: EdgeInsetsPropType.isRequired, }, getDefaultProps: function() { return { activeOpacity: 0.2, + touchRetentionOffset: TOUCH_RETENTION_OFFSET, }; }, @@ -119,7 +130,7 @@ var TouchableOpacity = React.createClass({ }, touchableGetPressRectOffset: function() { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! + return this.props.touchRetentionOffset; }, touchableGetHighlightDelayMS: function() { @@ -141,14 +152,6 @@ var TouchableOpacity = React.createClass({ }, }); -/** - * When the scroll view is disabled, this defines how far your touch may move - * off of the button, before deactivating the button. Once deactivated, try - * moving it back and you'll see that the button is once again reactivated! - * Move it back and forth several times while the scroll view is disabled. - */ -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; - var CHILD_REF = keyOf({childRef: null}); module.exports = TouchableOpacity; diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index cd9ea02fdf1517..5ae2c5cb88442c 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -11,20 +11,19 @@ */ 'use strict'; +var EdgeInsetsPropType = require('EdgeInsetsPropType'); var React = require('React'); var Touchable = require('Touchable'); var onlyChild = require('onlyChild'); -/** - * When the scroll view is disabled, this defines how far your touch may move - * off of the button, before deactivating the button. Once deactivated, try - * moving it back and you'll see that the button is once again reactivated! - * Move it back and forth several times while the scroll view is disabled. - */ -var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; +var TOUCH_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; type Event = Object; +type DefaultProps = { + touchRetentionOffset: typeof TOUCH_RETENTION_OFFSET; +}; + /** * Do not use unless you have a very good reason. All the elements that * respond to press should have a visual feedback when touched. This is @@ -42,6 +41,20 @@ var TouchableWithoutFeedback = React.createClass({ onPressIn: React.PropTypes.func, onPressOut: React.PropTypes.func, onLongPress: React.PropTypes.func, + /** + * When the scroll view is disabled, this defines how far your touch may + * move off of the button, before deactivating the button. Once deactivated, + * try moving it back and you'll see that the button is once again + * reactivated! Move it back and forth several times while the scroll view + * is disabled. Ensure you pass in a constant to reduce memory allocations. + */ + touchRetentionOffset: EdgeInsetsPropType.isRequired, + }, + + getDefaultProps: function(): DefaultProps { + return { + touchRetentionOffset: TOUCH_RETENTION_OFFSET, + } }, getInitialState: function() { @@ -68,8 +81,8 @@ var TouchableWithoutFeedback = React.createClass({ this.props.onLongPress && this.props.onLongPress(); }, - touchableGetPressRectOffset: function(): typeof PRESS_RECT_OFFSET { - return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! + touchableGetPressRectOffset: function(): typeof TOUCH_RETENTION_OFFSET { + return this.props.touchRetentionOffset; }, touchableGetHighlightDelayMS: function(): number {