nicehacker f7f347329e Add example on Components
Summary:
<!--
Thank you for sending the PR! We appreciate you spending the time to work on these changes.

Help us understand your motivation by explaining why you decided to make this change.

You can learn more about contributing to React Native here: http://facebook.github.io/react-native/docs/contributing.html

Happy contributing!

-->

Adding example on components section with [react-native-web-player](https://github.com/dabbott/react-native-web-player)

- ActivityIndicator
- TouchableOpacity
- TouchableHighlight

Screenshot on http://localhost:8079/react-native/docs/activityindicator.html
![react-native-activityindicator](https://user-images.githubusercontent.com/13135332/30432801-adca0982-9988-11e7-8e70-94ad9e42ea43.png)

Screenshot on http://localhost:8079/react-native/docs/touchableopacity.html
![react-native-touchableopacity](https://user-images.githubusercontent.com/13135332/30432718-80570554-9988-11e7-9c81-15ab98327fed.png)

Screenshot on http://localhost:8079/react-native/docs/touchablehighlight.html
![react-native-touchablehighlight](https://user-images.githubusercontent.com/13135332/30432733-8290fbb8-9988-11e7-94a1-86c3166e544d.png)
Closes https://github.com/facebook/react-native/pull/15950

Differential Revision: D5881366

Pulled By: hramos

fbshipit-source-id: 2926071723defedf9ed5cb1b1128204256c71dd9
2017-09-21 17:37:07 -07:00

265 lines
7.0 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 Easing = require('Easing');
var NativeMethodsMixin = require('NativeMethodsMixin');
var React = require('React');
var PropTypes = require('prop-types');
var TimerMixin = require('react-timer-mixin');
var Touchable = require('Touchable');
var TouchableWithoutFeedback = require('TouchableWithoutFeedback');
var createReactClass = require('create-react-class');
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.
*
* Opacity is controlled by wrapping the children in an Animated.View, which is
* added to the view hiearchy. Be aware that this can affect layout.
*
* Example:
*
* ```
* renderButton: function() {
* return (
* <TouchableOpacity onPress={this._onPressButton}>
* <Image
* style={styles.button}
* source={require('./myButton.png')}
* />
* </TouchableOpacity>
* );
* },
* ```
* ### Example
*
* ```ReactNativeWebPlayer
* import React, { Component } from 'react'
* import {
* AppRegistry,
* StyleSheet,
* TouchableOpacity,
* Text,
* View,
* } from 'react-native'
*
* class App extends Component {
* constructor(props) {
* super(props)
* this.state = { count: 0 }
* }
*
* onPress = () => {
* this.setState({
* count: this.state.count+1
* })
* }
*
* render() {
* return (
* <View style={styles.container}>
* <TouchableOpacity
* style={styles.button}
* onPress={this.onPress}
* >
* <Text> Touch Here </Text>
* </TouchableOpacity>
* <View style={[styles.countContainer]}>
* <Text style={[styles.countText]}>
* { this.state.count !== 0 ? this.state.count: null}
* </Text>
* </View>
* </View>
* )
* }
* }
*
* const styles = StyleSheet.create({
* container: {
* flex: 1,
* justifyContent: 'center',
* paddingHorizontal: 10
* },
* button: {
* alignItems: 'center',
* backgroundColor: '#DDDDDD',
* padding: 10
* },
* countContainer: {
* alignItems: 'center',
* padding: 10
* },
* countText: {
* color: '#FF00FF'
* }
* })
*
* AppRegistry.registerComponent('App', () => App)
* ```
*
*/
var TouchableOpacity = createReactClass({
displayName: 'TouchableOpacity',
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: PropTypes.number,
/**
* Apple TV parallax effects
*/
tvParallaxProperties: PropTypes.object,
},
getDefaultProps: function() {
return {
activeOpacity: 0.2,
};
},
getInitialState: function() {
return {
...this.touchableGetInitialState(),
anim: new Animated.Value(this._getChildStyleOpacityWithDefault()),
};
},
componentDidMount: function() {
ensurePositiveDelayProps(this.props);
},
componentWillReceiveProps: function(nextProps) {
ensurePositiveDelayProps(nextProps);
},
/**
* Animate the touchable to a new opacity.
*/
setOpacityTo: function(value: number, duration: number) {
Animated.timing(
this.state.anim,
{
toValue: value,
duration: duration,
easing: Easing.inOut(Easing.quad),
useNativeDriver: true,
}
).start();
},
/**
* `Touchable.Mixin` self callbacks. The mixin will invoke these if they are
* defined on your component.
*/
touchableHandleActivePressIn: function(e: Event) {
if (e.dispatchConfig.registrationName === 'onResponderGrant') {
this._opacityActive(0);
} else {
this._opacityActive(150);
}
this.props.onPressIn && this.props.onPressIn(e);
},
touchableHandleActivePressOut: function(e: Event) {
this._opacityInactive(250);
this.props.onPressOut && this.props.onPressOut(e);
},
touchableHandlePress: function(e: Event) {
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(duration: number) {
this.setOpacityTo(this.props.activeOpacity, duration);
},
_opacityInactive: function(duration: number) {
this.setOpacityTo(
this._getChildStyleOpacityWithDefault(),
duration
);
},
_getChildStyleOpacityWithDefault: function() {
var childStyle = flattenStyle(this.props.style) || {};
return 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}]}
nativeID={this.props.nativeID}
testID={this.props.testID}
onLayout={this.props.onLayout}
isTVSelectable={true}
tvParallaxProperties={this.props.tvParallaxProperties}
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;