Create a RTLExample for OSS

Reviewed By: fkgozali

Differential Revision: D3740559

fbshipit-source-id: 79271abe7ef5c723e934da24884ff777aea0acc3
This commit is contained in:
Mengjue Wang 2016-08-18 20:49:25 -07:00 committed by Facebook Github Bot 1
parent 1aef7e4629
commit 53d3f94175
5 changed files with 421 additions and 0 deletions

View File

@ -0,0 +1,411 @@
/**
* Copyright (c) 2013-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.
*
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Here's the Right-to-Left(RTL) example page with:
* - a button to force flip UI layout to RTL
* - base layout example and text example
* - two custom examples for RTL design
*
* @flow
*/
'use strict';
const React = require('react');
const ReactNative = require('react-native');
const {
Alert,
Animated,
I18nManager,
Image,
PanResponder,
PixelRatio,
ScrollView,
StyleSheet,
Text,
TouchableWithoutFeedback,
Switch,
View,
} = ReactNative;
const UIExplorerPage = require('./UIExplorerPage');
const UIExplorerBlock = require('./UIExplorerBlock');
const AnimatedImage = Animated.createAnimatedComponent(Image);
type State = {
toggleStatus: any,
pan: Object,
linear: Object,
isRTL: boolean,
windowWidth: number,
};
const SCALE = PixelRatio.get();
const IMAGE_DIMENSION = 100 * SCALE;
const IMAGE_SIZE = [IMAGE_DIMENSION, IMAGE_DIMENSION];
const IS_RTL = I18nManager.isRTL;
function ListItem(props) {
return (
<View style={styles.row}>
<View style={styles.column1}>
<Image
source={props.imageSource}
style={styles.icon}
/>
</View>
<View style={styles.column2}>
<View style={styles.textBox}>
<Text>
Text
Text
Text
</Text>
</View>
</View>
<View style={styles.column3}>
<View style={styles.smallButton}>
<Text style={styles.fontSizeSmall}>
Button
</Text>
</View>
</View>
</View>
);
}
function TextAlignmentExample(props) {
return (
<UIExplorerBlock
title={props.title}
description={props.description}>
<View>
<Text style={props.style}>
Left-to-Right language without text alignment.
</Text>
<Text style={props.style}>
من اليمين إلى اليسار اللغة دون محاذاة النص .
</Text>
<Text style={props.style}>
מימין לשמאל השפה בלי יישור טקסט .
</Text>
</View>
</UIExplorerBlock>
);
}
function AnimationBlock(props) {
return (
<View style={styles.block}>
<TouchableWithoutFeedback onPress={props.onPress}>
<AnimatedImage
style={[styles.img, props.imgStyle]}
source={require('./Thumbnails/poke.png')}
/>
</TouchableWithoutFeedback>
</View>
);
}
class RTLExample extends React.Component {
static title = 'RTLExample';
static description = 'Examples to show how to apply components to RTL layout.';
state: State;
props: any;
_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 (
<ScrollView
style={styles.container}
onLayout={this._onLayout}>
<UIExplorerPage title={'Right-to-Left (RTL) UI Layout'}>
<UIExplorerBlock title={'Current Layout Direction'}>
<View style={styles.directionBox}>
<Text style={styles.directionText}>
{this.state.isRTL ? 'Right-to-Left' : 'Left-to-Right'}
</Text>
</View>
</UIExplorerBlock>
<UIExplorerBlock title={'Quickly Test RTL Layout'}>
<View style={styles.flexDirectionRow}>
<Text style={styles.switchRowTextView}>
forceRTL
</Text>
<View style={styles.switchRowSwitchView}>
<Switch
onValueChange={this._onDirectionChange}
style={styles.rightAlignStyle}
value={this.state.isRTL} />
</View>
</View>
</UIExplorerBlock>
<UIExplorerBlock title={'A Simple List Item Layout'}>
<View style={styles.list}>
<ListItem imageSource={require('./Thumbnails/like.png')}/>
<ListItem imageSource={require('./Thumbnails/poke.png')}/>
</View>
</UIExplorerBlock>
<TextAlignmentExample
title={'Default Text Alignment'}
description={
'In iOS, it depends on active language. ' +
'In Android, it depends on the text content.'
}
style={styles.fontSizeSmall}
/>
<TextAlignmentExample
title={"Using textAlign: 'left'"}
description={
'In iOS, you must change active language to flip text alignment correctly.' +
'In Android, using forceRTL() flips alignment correctly.'
}
style={[styles.fontSizeSmall, styles.textAlignLeft]}
/>
<TextAlignmentExample
title={"Using textAlign: 'right'"}
description={'In iOS/Android, text alignment flips regardless of languages or text content.'}
style={[styles.fontSizeSmall, styles.textAlignRight]}
/>
<UIExplorerBlock title={'Working With Icons'}>
<View style={styles.flexDirectionRow}>
<View>
<Image
source={require('./Thumbnails/like.png')}
style={styles.image}
/>
<Text style={styles.fontSizeExtraSmall}>
Without directional meaning
</Text>
</View>
<View style={styles.rightAlignStyle}>
<Image
source={require('./Thumbnails/poke.png')}
style={[styles.image, styles.withRTLStyle]}
/>
<Text style={styles.fontSizeExtraSmall}>
With directional meaning
</Text>
</View>
</View>
</UIExplorerBlock>
<UIExplorerBlock
title={'Controlling Animation'}
description={'Animation direction according to layout'}
>
<View Style={styles.view}>
<AnimationBlock
onPress={this._linearTap.bind(this)}
imgStyle={{transform: [{translateX: this.state.linear}, {scaleX: IS_RTL ? -1 : 1}]}}
/>
</View>
</UIExplorerBlock>
</UIExplorerPage>
</ScrollView>
);
}
_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 = (refName: string, e: Object) => {
this.setState({
toggleStatus: {
...this.state.toggleStatus,
[refName]: !this.state.toggleStatus[refName],
},
});
const offset = IMAGE_SIZE[0] / SCALE / 2 + 10;
const toMaxDistance =
IS_RTL ?
-this.state.windowWidth / 2 + offset :
this.state.windowWidth / 2 - offset;
Animated.timing(this.state.linear, {
toValue: this.state.toggleStatus[refName] ? toMaxDistance : 0,
duration: 2000,
}).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 styles = StyleSheet.create({
container: {
backgroundColor: '#e9eaed',
paddingTop: 15,
},
directionBox: {
flex: 1,
backgroundColor: '#f8f8f8',
borderWidth: 0.5,
borderColor: 'black',
},
directionText: {
padding: 10,
fontSize: 16,
textAlign: 'center',
fontWeight: 'bold',
},
switchRowTextView: {
flex: 1,
marginBottom: 5,
marginTop: 5,
textAlign: 'center',
},
switchRowSwitchView: {
flex: 3,
},
rightAlignStyle: {
right: 10,
position: 'absolute',
},
list: {
height: 120,
marginBottom: 5,
borderTopWidth: 0.5,
borderLeftWidth: 0.5,
borderRightWidth: 0.5,
borderColor: '#e5e5e5',
},
row: {
height: 60,
flexDirection: 'row',
borderBottomWidth: 0.5,
borderColor: '#e5e5e5',
},
column1: {
width: 60,
},
column2: {
flex: 2.5,
padding: 6,
},
column3: {
flex: 1.5,
},
icon: {
width: 48,
height: 48,
margin: 6,
borderWidth: 0.5,
borderColor: '#e5e5e5',
},
withRTLStyle: {
transform: [{scaleX: IS_RTL ? -1 : 1}],
},
image: {
left: 30,
width: 48,
height: 48,
},
img: {
width: IMAGE_SIZE[0] / SCALE,
height: IMAGE_SIZE[1] / SCALE,
},
view: {
flex: 1,
},
block: {
padding: 10,
alignItems: 'center',
},
smallButton: {
top: 18,
borderRadius: 5,
height: 24,
width: 64,
backgroundColor: '#e5e5e5',
justifyContent: 'center',
alignItems: 'center',
},
fontSizeSmall:{
fontSize: 10,
},
fontSizeExtraSmall:{
fontSize: 8,
},
textAlignLeft: {
textAlign: 'left',
},
textAlignRight: {
textAlign: 'right',
},
textBox: {
width: 28,
},
flexDirectionRow: {
flexDirection: 'row',
},
});
module.exports = RTLExample;

View File

@ -189,6 +189,10 @@ const APIExamples = [
key: 'PointerEventsExample',
module: require('./PointerEventsExample'),
},
{
key: 'RTLExample',
module: require('./RTLExample'),
},
{
key: 'ShareExample',
module: require('./ShareExample'),

View File

@ -251,6 +251,10 @@ const APIExamples: Array<UIExplorerExample> = [
key: 'RCTRootViewIOSExample',
module: require('./RCTRootViewIOSExample'),
},
{
key: 'RTLExample',
module: require('./RTLExample'),
},
{
key: 'ShareExample',
module: require('./ShareExample'),

View File

@ -87,6 +87,7 @@ const ReactNative = {
get DatePickerAndroid() { return require('DatePickerAndroid'); },
get Dimensions() { return require('Dimensions'); },
get Easing() { return require('Easing'); },
get I18nManager() { return require('I18nManager'); },
get ImagePickerIOS() { return require('ImagePickerIOS'); },
get IntentAndroid() { return require('IntentAndroid'); },
get InteractionManager() { return require('InteractionManager'); },

View File

@ -99,6 +99,7 @@ var ReactNative = {
DatePickerAndroid: require('DatePickerAndroid'),
Dimensions: require('Dimensions'),
Easing: require('Easing'),
I18nManager: require('I18nManager'),
ImagePickerIOS: require('ImagePickerIOS'),
IntentAndroid: require('IntentAndroid'),
InteractionManager: require('InteractionManager'),