mirror of
https://github.com/status-im/react-native.git
synced 2025-01-10 17:45:59 +00:00
4f187074bf
Summary: With accessibility prop set to true, it is not possible to access childern elements. This makes it impossible to test Components with appium and releatives. This commit adds support to change accessiblity property on Touchable elements to overcome the aforementioned issue. Closes https://github.com/facebook/react-native/pull/8243 Differential Revision: D3462949 Pulled By: javache fbshipit-source-id: 65ce6507a1619218ab5b527c970a74af197ef462
185 lines
5.2 KiB
JavaScript
185 lines
5.2 KiB
JavaScript
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
* @providesModule TouchableOpacity
|
|
* @noflow
|
|
*/
|
|
'use strict';
|
|
|
|
// Note (avik): add @flow when Flow supports spread properties in propTypes
|
|
|
|
var Animated = require('Animated');
|
|
var NativeMethodsMixin = require('NativeMethodsMixin');
|
|
var React = require('React');
|
|
var TimerMixin = require('react-timer-mixin');
|
|
var Touchable = require('Touchable');
|
|
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
|
|
|
|
var ensurePositiveDelayProps = require('ensurePositiveDelayProps');
|
|
var flattenStyle = require('flattenStyle');
|
|
|
|
type Event = Object;
|
|
|
|
var PRESS_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.
|
|
* This is done without actually changing the view hierarchy, and in general is
|
|
* easy to add to an app without weird side-effects.
|
|
*
|
|
* Example:
|
|
*
|
|
* ```
|
|
* renderButton: function() {
|
|
* return (
|
|
* <TouchableOpacity onPress={this._onPressButton}>
|
|
* <Image
|
|
* style={styles.button}
|
|
* source={require('image!myButton')}
|
|
* />
|
|
* </TouchableOpacity>
|
|
* );
|
|
* },
|
|
* ```
|
|
*/
|
|
var TouchableOpacity = React.createClass({
|
|
mixins: [TimerMixin, Touchable.Mixin, NativeMethodsMixin],
|
|
|
|
propTypes: {
|
|
...TouchableWithoutFeedback.propTypes,
|
|
/**
|
|
* Determines what the opacity of the wrapped view should be when touch is
|
|
* active. Defaults to 0.2.
|
|
*/
|
|
activeOpacity: React.PropTypes.number,
|
|
},
|
|
|
|
getDefaultProps: function() {
|
|
return {
|
|
activeOpacity: 0.2,
|
|
};
|
|
},
|
|
|
|
getInitialState: function() {
|
|
return {
|
|
...this.touchableGetInitialState(),
|
|
anim: new Animated.Value(1),
|
|
};
|
|
},
|
|
|
|
componentDidMount: function() {
|
|
ensurePositiveDelayProps(this.props);
|
|
},
|
|
|
|
componentWillReceiveProps: function(nextProps) {
|
|
ensurePositiveDelayProps(nextProps);
|
|
},
|
|
|
|
/**
|
|
* Animate the touchable to a new opacity.
|
|
*/
|
|
setOpacityTo: function(value: number) {
|
|
Animated.timing(
|
|
this.state.anim,
|
|
{toValue: value, duration: 150}
|
|
).start();
|
|
},
|
|
|
|
/**
|
|
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
|
|
* defined on your component.
|
|
*/
|
|
touchableHandleActivePressIn: function(e: Event) {
|
|
this.clearTimeout(this._hideTimeout);
|
|
this._hideTimeout = null;
|
|
this._opacityActive();
|
|
this.props.onPressIn && this.props.onPressIn(e);
|
|
},
|
|
|
|
touchableHandleActivePressOut: function(e: Event) {
|
|
if (!this._hideTimeout) {
|
|
this._opacityInactive();
|
|
}
|
|
this.props.onPressOut && this.props.onPressOut(e);
|
|
},
|
|
|
|
touchableHandlePress: function(e: Event) {
|
|
this.clearTimeout(this._hideTimeout);
|
|
this._opacityActive();
|
|
this._hideTimeout = this.setTimeout(
|
|
this._opacityInactive,
|
|
this.props.delayPressOut || 100
|
|
);
|
|
this.props.onPress && this.props.onPress(e);
|
|
},
|
|
|
|
touchableHandleLongPress: function(e: Event) {
|
|
this.props.onLongPress && this.props.onLongPress(e);
|
|
},
|
|
|
|
touchableGetPressRectOffset: function() {
|
|
return this.props.pressRetentionOffset || PRESS_RETENTION_OFFSET;
|
|
},
|
|
|
|
touchableGetHitSlop: function() {
|
|
return this.props.hitSlop;
|
|
},
|
|
|
|
touchableGetHighlightDelayMS: function() {
|
|
return this.props.delayPressIn || 0;
|
|
},
|
|
|
|
touchableGetLongPressDelayMS: function() {
|
|
return this.props.delayLongPress === 0 ? 0 :
|
|
this.props.delayLongPress || 500;
|
|
},
|
|
|
|
touchableGetPressOutDelayMS: function() {
|
|
return this.props.delayPressOut;
|
|
},
|
|
|
|
_opacityActive: function() {
|
|
this.setOpacityTo(this.props.activeOpacity);
|
|
},
|
|
|
|
_opacityInactive: function() {
|
|
this.clearTimeout(this._hideTimeout);
|
|
this._hideTimeout = null;
|
|
var childStyle = flattenStyle(this.props.style) || {};
|
|
this.setOpacityTo(
|
|
childStyle.opacity === undefined ? 1 : childStyle.opacity
|
|
);
|
|
},
|
|
|
|
render: function() {
|
|
return (
|
|
<Animated.View
|
|
accessible={this.props.accessible !== false}
|
|
accessibilityLabel={this.props.accessibilityLabel}
|
|
accessibilityComponentType={this.props.accessibilityComponentType}
|
|
accessibilityTraits={this.props.accessibilityTraits}
|
|
style={[this.props.style, {opacity: this.state.anim}]}
|
|
testID={this.props.testID}
|
|
onLayout={this.props.onLayout}
|
|
hitSlop={this.props.hitSlop}
|
|
onStartShouldSetResponder={this.touchableHandleStartShouldSetResponder}
|
|
onResponderTerminationRequest={this.touchableHandleResponderTerminationRequest}
|
|
onResponderGrant={this.touchableHandleResponderGrant}
|
|
onResponderMove={this.touchableHandleResponderMove}
|
|
onResponderRelease={this.touchableHandleResponderRelease}
|
|
onResponderTerminate={this.touchableHandleResponderTerminate}>
|
|
{this.props.children}
|
|
{Touchable.renderDebugView({color: 'cyan', hitSlop: this.props.hitSlop})}
|
|
</Animated.View>
|
|
);
|
|
},
|
|
});
|
|
|
|
module.exports = TouchableOpacity;
|