From d5b0d845efadfe15c5f0425d417a508e35435bdf Mon Sep 17 00:00:00 2001 From: James Ide Date: Thu, 26 Feb 2015 10:03:22 -0800 Subject: [PATCH] [Touch] Suite of touchable events on TouchableHighlight/Opacity Summary: The following props are now supported on TouchableHighlight/Opacity components: - onPress (was there before) - onPressIn - onPressOut - onLongPress There is a `TouchableFeedbackPropType` that is shared amongst the Touchable family for consistency. Added UIExplorer example to demonstrate and test. Fixes #101. Closes https://github.com/facebook/react-native/pull/102 Github Author: James Ide Test Plan: Imported from GitHub, without a `Test Plan:` line. --- Examples/UIExplorer/TouchableExample.js | 56 ++++++++++++++++++- .../Touchable/TouchableFeedbackPropType.js | 22 ++++++++ .../Touchable/TouchableHighlight.js | 8 +++ .../Components/Touchable/TouchableOpacity.js | 13 +++-- .../Touchable/TouchableWithoutFeedback.js | 9 +-- 5 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 Libraries/Components/Touchable/TouchableFeedbackPropType.js diff --git a/Examples/UIExplorer/TouchableExample.js b/Examples/UIExplorer/TouchableExample.js index 7aa2be01c68be3..66a919a3cdd29b 100644 --- a/Examples/UIExplorer/TouchableExample.js +++ b/Examples/UIExplorer/TouchableExample.js @@ -12,6 +12,7 @@ var { StyleSheet, Text, TouchableHighlight, + TouchableOpacity, View, } = React; @@ -57,6 +58,13 @@ exports.examples = [ render: function() { return ; }, +}, { + title: 'Touchable feedback events', + description: ' components accept onPress, onPressIn, ' + + 'onPressOut, and onLongPress as props.', + render: function() { + return ; + }, }]; var TextOnPressBox = React.createClass({ @@ -95,11 +103,46 @@ var TextOnPressBox = React.createClass({ } }); +var TouchableFeedbackEvents = React.createClass({ + getInitialState: function() { + return { + eventLog: [], + }; + }, + render: function() { + return ( + + + this._appendEvent('press')} + onPressIn={() => this._appendEvent('pressIn')} + onPressOut={() => this._appendEvent('pressOut')} + onLongPress={() => this._appendEvent('longPress')}> + + Press Me + + + + + {this.state.eventLog.map((e, ii) => {e})} + + + ); + }, + _appendEvent: function(eventName) { + var limit = 6; + var eventLog = this.state.eventLog.slice(0, limit - 1); + eventLog.unshift(eventName); + this.setState({eventLog}); + }, +}); + var heartImage = {uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small'}; var styles = StyleSheet.create({ row: { - alignItems: 'center', + justifyContent: 'center', flexDirection: 'row', }, icon: { @@ -113,6 +156,9 @@ var styles = StyleSheet.create({ text: { fontSize: 16, }, + button: { + color: '#007AFF', + }, wrapper: { borderRadius: 8, }, @@ -127,6 +173,14 @@ var styles = StyleSheet.create({ borderColor: '#f0f0f0', backgroundColor: '#f9f9f9', }, + eventLogBox: { + padding: 10, + margin: 10, + height: 120, + borderWidth: 1 / PixelRatio.get(), + borderColor: '#f0f0f0', + backgroundColor: '#f9f9f9', + }, textBlock: { fontWeight: 'bold', color: 'blue', diff --git a/Libraries/Components/Touchable/TouchableFeedbackPropType.js b/Libraries/Components/Touchable/TouchableFeedbackPropType.js new file mode 100644 index 00000000000000..336b091c629fdb --- /dev/null +++ b/Libraries/Components/Touchable/TouchableFeedbackPropType.js @@ -0,0 +1,22 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + * + * @providesModule TouchableFeedbackPropType + * @flow + */ +'use strict'; + +var { PropTypes } = require('React'); + +var TouchableFeedbackPropType = { + /** + * Called when the touch is released, but not if cancelled (e.g. by a scroll + * that steals the responder lock). + */ + onPress: PropTypes.func, + onPressIn: PropTypes.func, + onPressOut: PropTypes.func, + onLongPress: PropTypes.func, +}; + +module.exports = TouchableFeedbackPropType; diff --git a/Libraries/Components/Touchable/TouchableHighlight.js b/Libraries/Components/Touchable/TouchableHighlight.js index da721cff8a6d3c..9381f52d628178 100644 --- a/Libraries/Components/Touchable/TouchableHighlight.js +++ b/Libraries/Components/Touchable/TouchableHighlight.js @@ -11,6 +11,7 @@ var ReactIOSViewAttributes = require('ReactIOSViewAttributes'); var StyleSheet = require('StyleSheet'); var TimerMixin = require('TimerMixin'); var Touchable = require('Touchable'); +var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); var View = require('View'); var cloneWithProps = require('cloneWithProps'); @@ -50,6 +51,7 @@ var DEFAULT_PROPS = { var TouchableHighlight = React.createClass({ propTypes: { + ...TouchableFeedbackPropType, /** * Called when the touch is released, but not if cancelled (e.g. by * a scroll that steals the responder lock). @@ -127,12 +129,14 @@ var TouchableHighlight = React.createClass({ this.clearTimeout(this._hideTimeout); this._hideTimeout = null; this._showUnderlay(); + this.props.onPressIn && this.props.onPressIn(); }, touchableHandleActivePressOut: function() { if (!this._hideTimeout) { this._hideUnderlay(); } + this.props.onPressOut && this.props.onPressOut(); }, touchableHandlePress: function() { @@ -142,6 +146,10 @@ var TouchableHighlight = React.createClass({ this.props.onPress && this.props.onPress(); }, + touchableHandleLongPress: function() { + this.props.onLongPress && this.props.onLongPress(); + }, + touchableGetPressRectOffset: function() { return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! }, diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index a1bd8f4e359eee..cb68d6df37cfd2 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -9,6 +9,7 @@ var NativeMethodsMixin = require('NativeMethodsMixin'); var POPAnimationMixin = require('POPAnimationMixin'); var React = require('React'); var Touchable = require('Touchable'); +var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); var cloneWithProps = require('cloneWithProps'); var ensureComponentIsNative = require('ensureComponentIsNative'); @@ -41,11 +42,7 @@ var TouchableOpacity = React.createClass({ mixins: [Touchable.Mixin, NativeMethodsMixin, POPAnimationMixin], propTypes: { - /** - * Called when the touch is released, but not if cancelled (e.g. by - * a scroll that steals the responder lock). - */ - onPress: React.PropTypes.func, + ...TouchableFeedbackPropType, /** * Determines what the opacity of the wrapped view should be when touch is * active. @@ -97,10 +94,12 @@ var TouchableOpacity = React.createClass({ this.refs[CHILD_REF].setNativeProps({ opacity: this.props.activeOpacity }); + this.props.onPressIn && this.props.onPressIn(); }, touchableHandleActivePressOut: function() { this.setOpacityTo(1.0); + this.props.onPressOut && this.props.onPressOut(); }, touchableHandlePress: function() { @@ -108,6 +107,10 @@ var TouchableOpacity = React.createClass({ this.props.onPress && this.props.onPress(); }, + touchableHandleLongPress: function() { + this.props.onLongPress && this.props.onLongPress(); + }, + touchableGetPressRectOffset: function() { return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! }, diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 66a82d59c75cbb..74fbf43a1e1e24 100644 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -7,7 +7,7 @@ var React = require('React'); var Touchable = require('Touchable'); -var View = require('View'); +var TouchableFeedbackPropType = require('TouchableFeedbackPropType'); var copyProperties = require('copyProperties'); var onlyChild = require('onlyChild'); @@ -29,12 +29,7 @@ var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30}; var TouchableWithoutFeedback = React.createClass({ mixins: [Touchable.Mixin], - propTypes: { - onPress: React.PropTypes.func, - onPressIn: React.PropTypes.func, - onPressOut: React.PropTypes.func, - onLongPress: React.PropTypes.func, - }, + propTypes: TouchableFeedbackPropType, getInitialState: function() { return this.touchableGetInitialState();