[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 <ide@jameside.com>

Test Plan: Imported from GitHub, without a `Test Plan:` line.
This commit is contained in:
James Ide 2015-02-26 10:03:22 -08:00
Родитель d0d774d403
Коммит 337329451d
5 изменённых файлов: 95 добавлений и 13 удалений

Просмотреть файл

@ -12,6 +12,7 @@ var {
StyleSheet, StyleSheet,
Text, Text,
TouchableHighlight, TouchableHighlight,
TouchableOpacity,
View, View,
} = React; } = React;
@ -57,6 +58,13 @@ exports.examples = [
render: function() { render: function() {
return <TextOnPressBox />; return <TextOnPressBox />;
}, },
}, {
title: 'Touchable feedback events',
description: '<Touchable*> components accept onPress, onPressIn, ' +
'onPressOut, and onLongPress as props.',
render: function() {
return <TouchableFeedbackEvents />;
},
}]; }];
var TextOnPressBox = React.createClass({ var TextOnPressBox = React.createClass({
@ -95,11 +103,46 @@ var TextOnPressBox = React.createClass({
} }
}); });
var TouchableFeedbackEvents = React.createClass({
getInitialState: function() {
return {
eventLog: [],
};
},
render: function() {
return (
<View>
<View style={[styles.row, {justifyContent: 'center'}]}>
<TouchableOpacity
style={styles.wrapper}
onPress={() => this._appendEvent('press')}
onPressIn={() => this._appendEvent('pressIn')}
onPressOut={() => this._appendEvent('pressOut')}
onLongPress={() => this._appendEvent('longPress')}>
<Text style={styles.button}>
Press Me
</Text>
</TouchableOpacity>
</View>
<View style={styles.eventLogBox}>
{this.state.eventLog.map((e, ii) => <Text key={ii}>{e}</Text>)}
</View>
</View>
);
},
_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 heartImage = {uri: 'https://pbs.twimg.com/media/BlXBfT3CQAA6cVZ.png:small'};
var styles = StyleSheet.create({ var styles = StyleSheet.create({
row: { row: {
alignItems: 'center', justifyContent: 'center',
flexDirection: 'row', flexDirection: 'row',
}, },
icon: { icon: {
@ -113,6 +156,9 @@ var styles = StyleSheet.create({
text: { text: {
fontSize: 16, fontSize: 16,
}, },
button: {
color: '#007AFF',
},
wrapper: { wrapper: {
borderRadius: 8, borderRadius: 8,
}, },
@ -127,6 +173,14 @@ var styles = StyleSheet.create({
borderColor: '#f0f0f0', borderColor: '#f0f0f0',
backgroundColor: '#f9f9f9', backgroundColor: '#f9f9f9',
}, },
eventLogBox: {
padding: 10,
margin: 10,
height: 120,
borderWidth: 1 / PixelRatio.get(),
borderColor: '#f0f0f0',
backgroundColor: '#f9f9f9',
},
textBlock: { textBlock: {
fontWeight: 'bold', fontWeight: 'bold',
color: 'blue', color: 'blue',

Просмотреть файл

@ -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;

Просмотреть файл

@ -11,6 +11,7 @@ var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var StyleSheet = require('StyleSheet'); var StyleSheet = require('StyleSheet');
var TimerMixin = require('TimerMixin'); var TimerMixin = require('TimerMixin');
var Touchable = require('Touchable'); var Touchable = require('Touchable');
var TouchableFeedbackPropType = require('TouchableFeedbackPropType');
var View = require('View'); var View = require('View');
var cloneWithProps = require('cloneWithProps'); var cloneWithProps = require('cloneWithProps');
@ -50,6 +51,7 @@ var DEFAULT_PROPS = {
var TouchableHighlight = React.createClass({ var TouchableHighlight = React.createClass({
propTypes: { propTypes: {
...TouchableFeedbackPropType,
/** /**
* Called when the touch is released, but not if cancelled (e.g. by * Called when the touch is released, but not if cancelled (e.g. by
* a scroll that steals the responder lock). * a scroll that steals the responder lock).
@ -127,12 +129,14 @@ var TouchableHighlight = React.createClass({
this.clearTimeout(this._hideTimeout); this.clearTimeout(this._hideTimeout);
this._hideTimeout = null; this._hideTimeout = null;
this._showUnderlay(); this._showUnderlay();
this.props.onPressIn && this.props.onPressIn();
}, },
touchableHandleActivePressOut: function() { touchableHandleActivePressOut: function() {
if (!this._hideTimeout) { if (!this._hideTimeout) {
this._hideUnderlay(); this._hideUnderlay();
} }
this.props.onPressOut && this.props.onPressOut();
}, },
touchableHandlePress: function() { touchableHandlePress: function() {
@ -142,6 +146,10 @@ var TouchableHighlight = React.createClass({
this.props.onPress && this.props.onPress(); this.props.onPress && this.props.onPress();
}, },
touchableHandleLongPress: function() {
this.props.onLongPress && this.props.onLongPress();
},
touchableGetPressRectOffset: function() { touchableGetPressRectOffset: function() {
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
}, },

Просмотреть файл

@ -9,6 +9,7 @@ var NativeMethodsMixin = require('NativeMethodsMixin');
var POPAnimationMixin = require('POPAnimationMixin'); var POPAnimationMixin = require('POPAnimationMixin');
var React = require('React'); var React = require('React');
var Touchable = require('Touchable'); var Touchable = require('Touchable');
var TouchableFeedbackPropType = require('TouchableFeedbackPropType');
var cloneWithProps = require('cloneWithProps'); var cloneWithProps = require('cloneWithProps');
var ensureComponentIsNative = require('ensureComponentIsNative'); var ensureComponentIsNative = require('ensureComponentIsNative');
@ -41,11 +42,7 @@ var TouchableOpacity = React.createClass({
mixins: [Touchable.Mixin, NativeMethodsMixin, POPAnimationMixin], mixins: [Touchable.Mixin, NativeMethodsMixin, POPAnimationMixin],
propTypes: { propTypes: {
/** ...TouchableFeedbackPropType,
* Called when the touch is released, but not if cancelled (e.g. by
* a scroll that steals the responder lock).
*/
onPress: React.PropTypes.func,
/** /**
* Determines what the opacity of the wrapped view should be when touch is * Determines what the opacity of the wrapped view should be when touch is
* active. * active.
@ -97,10 +94,12 @@ var TouchableOpacity = React.createClass({
this.refs[CHILD_REF].setNativeProps({ this.refs[CHILD_REF].setNativeProps({
opacity: this.props.activeOpacity opacity: this.props.activeOpacity
}); });
this.props.onPressIn && this.props.onPressIn();
}, },
touchableHandleActivePressOut: function() { touchableHandleActivePressOut: function() {
this.setOpacityTo(1.0); this.setOpacityTo(1.0);
this.props.onPressOut && this.props.onPressOut();
}, },
touchableHandlePress: function() { touchableHandlePress: function() {
@ -108,6 +107,10 @@ var TouchableOpacity = React.createClass({
this.props.onPress && this.props.onPress(); this.props.onPress && this.props.onPress();
}, },
touchableHandleLongPress: function() {
this.props.onLongPress && this.props.onLongPress();
},
touchableGetPressRectOffset: function() { touchableGetPressRectOffset: function() {
return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant! return PRESS_RECT_OFFSET; // Always make sure to predeclare a constant!
}, },

Просмотреть файл

@ -7,7 +7,7 @@
var React = require('React'); var React = require('React');
var Touchable = require('Touchable'); var Touchable = require('Touchable');
var View = require('View'); var TouchableFeedbackPropType = require('TouchableFeedbackPropType');
var copyProperties = require('copyProperties'); var copyProperties = require('copyProperties');
var onlyChild = require('onlyChild'); var onlyChild = require('onlyChild');
@ -29,12 +29,7 @@ var PRESS_RECT_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
var TouchableWithoutFeedback = React.createClass({ var TouchableWithoutFeedback = React.createClass({
mixins: [Touchable.Mixin], mixins: [Touchable.Mixin],
propTypes: { propTypes: TouchableFeedbackPropType,
onPress: React.PropTypes.func,
onPressIn: React.PropTypes.func,
onPressOut: React.PropTypes.func,
onLongPress: React.PropTypes.func,
},
getInitialState: function() { getInitialState: function() {
return this.touchableGetInitialState(); return this.touchableGetInitialState();