diff --git a/RNTester/js/RTLExample.js b/RNTester/js/RTLExample.js index 96fe2fc8a2ac24..a58b744709ab46 100644 --- a/RNTester/js/RTLExample.js +++ b/RNTester/js/RTLExample.js @@ -16,9 +16,7 @@ const { Animated, I18nManager, Image, - PanResponder, PixelRatio, - ScrollView, StyleSheet, Text, TouchableWithoutFeedback, @@ -28,14 +26,20 @@ const { } = ReactNative; const Platform = require('Platform'); -const RNTesterPage = require('./RNTesterPage'); -const RNTesterBlock = require('./RNTesterBlock'); - type State = { toggleStatus: any, pan: Object, linear: Object, isRTL: boolean, +}; + +type RTLToggleState = { + isRTL: boolean, +}; + +type AnimationState = { + toggleStatus: any, + linear: Object, windowWidth: number, }; @@ -65,10 +69,11 @@ function ListItem(props) { ); } -function TextAlignmentExample(props) { +const TextAlignmentExample = withRTLState(({isRTL, setRTL, ...props}) => { return ( - - + + + Left-to-Right language without text alignment. @@ -84,9 +89,37 @@ function TextAlignmentExample(props) { '\u05D9\u05D9\u05E9\u05D5\u05E8 \u05D8\u05E7\u05E1\u05D8'} - + ); -} +}); + +const IconsExample = withRTLState(({isRTL, setRTL}) => { + return ( + + + + + + + Without directional meaning + + + + + + With directional meaning + + + + + ); +}); function AnimationBlock(props) { return ( @@ -116,7 +149,9 @@ function withRTLState(Component) { render() { const setRTL = isRTL => this.setState({isRTL: isRTL}); - return ; + return ( + + ); } }; } @@ -137,11 +172,124 @@ const RTLToggler = ({isRTL, setRTL}) => { ); }; +class RTLToggleExample extends React.Component { + constructor(props: Object) { + super(props); + + this.state = { + isRTL: IS_RTL, + }; + } + + render() { + return ( + + + + {this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'} + + + + forceRTL + + + + + + ); + } + + _onDirectionChange = () => { + I18nManager.forceRTL(!this.state.isRTL); + this.setState({isRTL: !this.state.isRTL}); + Alert.alert( + 'Reload this page', + 'Please reload this page to change the UI direction! ' + + 'All examples in this app will be affected. ' + + 'Check them out to see what they look like in RTL layout.', + ); + }; +} + +const SimpleListItemExample = withRTLState(({isRTL, setRTL}) => { + return ( + + + + + + + + ); +}); + +const AnimationContainer = withRTLState(({isRTL, setRTL}) => { + return ; +}); + +class AnimationExample extends React.Component { + constructor(props: Object) { + super(props); + + this.state = { + toggleStatus: {}, + linear: new Animated.Value(0), + windowWidth: 0, + }; + } + + render() { + return ( + + + + + + + ); + } + + _onLayout = (e: Object) => { + this.setState({ + windowWidth: e.nativeEvent.layout.width, + }); + }; + + _linearTap = (e: Object) => { + this.setState({ + toggleStatus: { + ...this.state.toggleStatus, + [e]: !this.state.toggleStatus[e], + }, + }); + const offset = IMAGE_SIZE[0] / SCALE / 2 + 10; + const toMaxDistance = + (this.props.isRTL ? -1 : 1) * (this.state.windowWidth / 2 - offset); + Animated.timing(this.state.linear, { + toValue: this.state.toggleStatus[e] ? toMaxDistance : 0, + duration: 2000, + useNativeDriver: true, + }).start(); + }; +} + const PaddingExample = withRTLState(({isRTL, setRTL}) => { const color = 'teal'; return ( - + Styles paddingStart: 50, paddingEnd: 10 @@ -169,13 +317,13 @@ const PaddingExample = withRTLState(({isRTL, setRTL}) => { - + ); }); const MarginExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles marginStart: 50, marginEnd: 10 @@ -203,13 +351,13 @@ const MarginExample = withRTLState(({isRTL, setRTL}) => { - + ); }); const PositionExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles start: 50 @@ -253,19 +401,19 @@ const PositionExample = withRTLState(({isRTL, setRTL}) => { - + ); }); const BorderWidthExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles borderStartWidth: 10, borderEndWidth: 50 Demo: - + { - + ); }); const BorderColorExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles borderStartColor: 'red', borderEndColor: 'green', Demo: - + { - + ); }); const BorderRadiiExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles borderTopStartRadius: 10, borderTopEndRadius: 20, @@ -316,7 +464,7 @@ const BorderRadiiExample = withRTLState(({isRTL, setRTL}) => { borderBottomEndRadius: 40 Demo: - + { - + ); }); const BorderExample = withRTLState(({isRTL, setRTL}) => { return ( - + Styles borderStartColor: 'red', borderEndColor: 'green', @@ -349,7 +497,7 @@ const BorderExample = withRTLState(({isRTL, setRTL}) => { borderBottomEndRadius: 40 Demo: - + { - + ); }); -class RTLExample extends React.Component { - _panResponder: Object; - - constructor(props: Object) { - super(props); - const pan = new Animated.ValueXY(); - - this._panResponder = PanResponder.create({ - onStartShouldSetPanResponder: () => true, - onPanResponderGrant: this._onPanResponderGrant, - onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]), - onPanResponderRelease: this._onPanResponderEnd, - onPanResponderTerminate: this._onPanResponderEnd, - }); - - this.state = { - toggleStatus: {}, - pan, - linear: new Animated.Value(0), - isRTL: IS_RTL, - windowWidth: 0, - }; - } - - render() { - return ( - - - - - - {this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'} - - - - - - forceRTL - - - - - - - - - - - - - - - - - - - - Without directional meaning - - - - - - With directional meaning - - - - - - - - - - - - - - - - - - - ); - } - - _onLayout = (e: Object) => { - this.setState({ - windowWidth: e.nativeEvent.layout.width, - }); - }; - - _onDirectionChange = () => { - I18nManager.forceRTL(!this.state.isRTL); - this.setState({isRTL: !this.state.isRTL}); - Alert.alert( - 'Reload this page', - 'Please reload this page to change the UI direction! ' + - 'All examples in this app will be affected. ' + - 'Check them out to see what they look like in RTL layout.', - ); - }; - - _linearTap = (e: Object) => { - this.setState({ - toggleStatus: { - ...this.state.toggleStatus, - [e]: !this.state.toggleStatus[e], - }, - }); - const offset = IMAGE_SIZE[0] / SCALE / 2 + 10; - const toMaxDistance = - (IS_RTL ? -1 : 1) * (this.state.windowWidth / 2 - offset); - Animated.timing(this.state.linear, { - toValue: this.state.toggleStatus[e] ? toMaxDistance : 0, - duration: 2000, - useNativeDriver: true, - }).start(); - }; - - _onPanResponderGrant = (e: Object, gestureState: Object) => { - this.state.pan.stopAnimation(value => { - this.state.pan.setOffset(value); - }); - }; - - _onPanResponderEnd = (e: Object, gestureState: Object) => { - this.state.pan.flattenOffset(); - Animated.sequence([ - Animated.decay(this.state.pan, { - velocity: {x: gestureState.vx, y: gestureState.vy}, - deceleration: 0.995, - }), - Animated.spring(this.state.pan, {toValue: {x: 0, y: 0}}), - ]).start(); - }; -} +const directionStyle = isRTL => + Platform.OS === 'ios' ? {direction: isRTL ? 'rtl' : 'ltr'} : null; const styles = StyleSheet.create({ container: { @@ -567,6 +532,7 @@ const styles = StyleSheet.create({ backgroundColor: '#f8f8f8', borderWidth: 0.5, borderColor: 'black', + marginBottom: 15, }, directionText: { padding: 10, @@ -679,9 +645,105 @@ exports.title = 'RTLExample'; exports.description = 'Examples to show how to apply components to RTL layout.'; exports.examples = [ { - title: 'Simple RTL', - render: function(): React.Element { - return ; + title: 'Current Layout Direction', + render: function(): React.Element { + return ; + }, + }, + { + title: 'A Simple List Item Layout', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Default Text Alignment', + description: + 'In iOS, it depends on active language. ' + + 'In Android, it depends on the text content.', + render: function(): React.Element { + return ; + }, + }, + { + title: "Using textAlign: 'left'", + description: + 'In iOS/Android, text alignment flips regardless of ' + + 'languages or text content.', + render: function(): React.Element { + return ( + + ); + }, + }, + { + title: "Using textAlign: 'right'", + description: + 'In iOS/Android, text alignment flips regardless of ' + + 'languages or text content.', + render: function(): React.Element { + return ( + + ); + }, + }, + { + title: 'Working With Icons', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Controlling Animation', + description: 'Animation direction according to layout', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Padding Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Margin Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Position Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Border Width Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Border Color Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Border Radii Start/End', + render: function(): React.Element { + return ; + }, + }, + { + title: 'Border', + render: function(): React.Element { + return ; }, }, ];