TouchableOpacity: Respond instantly to first touch

Summary:
On iOS, when you press down native fading components, they become
transparent instantly, but then have an animated fade in/out if you
move your finger in/out of their hit box.

On react-native currently, the touchdown fades, instead of providing
instant feedback, which doesn't feel right on iOS.

I'm less familiar with Android conventions, but it seems to use fading
components for buttons less often, instead using the ripple effect from
TouchableNativeFeedback. In either case, instant feedback seems better
for the user.
Closes https://github.com/facebook/react-native/pull/10866

Differential Revision: D4175854

Pulled By: hramos

fbshipit-source-id: d993231074e8190cf4ba7ca86dc24299f05d5d8f
This commit is contained in:
Aria Buckles 2016-11-14 09:29:18 -08:00 committed by Facebook Github Bot
parent be5e300abf
commit fa8c536b31
2 changed files with 16 additions and 8 deletions

View File

@ -302,7 +302,10 @@ class TimingAnimation extends Animation {
this.__onEnd = onEnd;
var start = () => {
if (this._duration === 0) {
// Animations that sometimes have 0 duration and sometimes do not
// still need to use the native driver when duration is 0 so as to
// not cause intermixed JS and native animations.
if (this._duration === 0 && !this._useNativeDriver) {
this._onUpdate(this._toValue);
this.__debouncedOnEnd({finished: true});
} else {

View File

@ -84,10 +84,10 @@ var TouchableOpacity = React.createClass({
/**
* Animate the touchable to a new opacity.
*/
setOpacityTo: function(value: number) {
setOpacityTo: function(value: number, duration: number = 150) {
Animated.timing(
this.state.anim,
{toValue: value, duration: 150, useNativeDriver: true}
{toValue: value, duration: duration, useNativeDriver: true}
).start();
},
@ -98,7 +98,11 @@ var TouchableOpacity = React.createClass({
touchableHandleActivePressIn: function(e: Event) {
this.clearTimeout(this._hideTimeout);
this._hideTimeout = null;
this._opacityActive();
if (e.dispatchConfig.registrationName === 'onResponderGrant') {
this._opacityActive(0);
} else {
this._opacityActive(150);
}
this.props.onPressIn && this.props.onPressIn(e);
},
@ -111,7 +115,7 @@ var TouchableOpacity = React.createClass({
touchableHandlePress: function(e: Event) {
this.clearTimeout(this._hideTimeout);
this._opacityActive();
this._opacityActive(150);
this._hideTimeout = this.setTimeout(
this._opacityInactive,
this.props.delayPressOut || 100
@ -144,8 +148,8 @@ var TouchableOpacity = React.createClass({
return this.props.delayPressOut;
},
_opacityActive: function() {
this.setOpacityTo(this.props.activeOpacity);
_opacityActive: function(duration: number) {
this.setOpacityTo(this.props.activeOpacity, duration);
},
_opacityInactive: function() {
@ -153,7 +157,8 @@ var TouchableOpacity = React.createClass({
this._hideTimeout = null;
var childStyle = flattenStyle(this.props.style) || {};
this.setOpacityTo(
childStyle.opacity === undefined ? 1 : childStyle.opacity
childStyle.opacity === undefined ? 1 : childStyle.opacity,
150
);
},