-
Notifications
You must be signed in to change notification settings - Fork 904
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLI: Add basic Navigation template (Chat)
Summary: Basic template using 'react-navigation' to make it easy to get started. Not duplicating all the files in `android` and `ios` folders. These will be taken from the `HelloWorld` template. Let's not duplicate all of these files (it's a lot and they are large, especially the Xcode projects). **Test plan (required)** The app works locally. This PR is just a preparation for a next PR that will add support for 'react-native init --template Navigation'. Will have a proper test plan there. Closes facebook/react-native#12153 Differential Revision: D4494776 Pulled By: mkonicek fbshipit-source-id: b43eafd7a1424477f9493a3eb4083ba4dd3d3846
- Loading branch information
1 parent
bbaea58
commit 19daa55
Showing
12 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* @flow */ | ||
|
||
import React, { PropTypes, Component } from 'react'; | ||
import { | ||
Platform, | ||
View, | ||
Keyboard, | ||
LayoutAnimation, | ||
UIManager, | ||
} from 'react-native'; | ||
|
||
type Props = { | ||
offset?: number; | ||
} | ||
|
||
type State = { | ||
keyboardHeight: number | ||
} | ||
|
||
// Consider contributing this to the popular library: | ||
// https://github.com/Andr3wHur5t/react-native-keyboard-spacer | ||
|
||
/** | ||
* On iOS, the software keyboard covers the screen by default. | ||
* This is not desirable if there are TextInputs near the bottom of the screen - | ||
* they would be covered by the keyboard and the user cannot see what they | ||
* are typing. | ||
* To get around this problem, place a `<KeyboardSpacer />` at the bottom | ||
* of the screen, after your TextInputs. The keyboard spacer has size 0 and | ||
* when the keyboard is shown it will grow to the same size as the keyboard, | ||
* shifting all views above it and therefore making them visible. | ||
* | ||
* On Android, this component is not needed because resizing the UI when | ||
* the keyboard is shown is supported by the OS. | ||
* Simply set the `android:windowSoftInputMode="adjustResize"` attribute | ||
* on the <activity> element in your AndroidManifest.xml. | ||
* | ||
* How is this different from KeyboardAvoidingView? | ||
* The KeyboardAvoidingView doesn't work when used together with | ||
* a ScrollView/ListView. | ||
*/ | ||
const KeyboardSpacer = () => ( | ||
Platform.OS === 'ios' ? <KeyboardSpacerIOS /> : null | ||
) | ||
|
||
class KeyboardSpacerIOS extends Component<Props, Props, State> { | ||
static propTypes = { | ||
offset: PropTypes.number, | ||
}; | ||
|
||
static defaultProps = { | ||
offset: 0, | ||
}; | ||
|
||
state: State = { | ||
keyboardHeight: 0, | ||
}; | ||
|
||
componentWillMount() { | ||
this._registerEvents(); | ||
} | ||
|
||
componentWillUnmount() { | ||
this._unRegisterEvents(); | ||
} | ||
|
||
_keyboardWillShowSubscription: { remove: Function }; | ||
_keyboardWillHideSubscription: { remove: Function }; | ||
|
||
_registerEvents = () => { | ||
this._keyboardWillShowSubscription = Keyboard.addListener( | ||
'keyboardWillShow', | ||
this._keyboardWillShow | ||
); | ||
this._keyboardWillHideSubscription = Keyboard.addListener( | ||
'keyboardWillHide', | ||
this._keyboardWillHide | ||
); | ||
}; | ||
|
||
_unRegisterEvents = () => { | ||
this._keyboardWillShowSubscription.remove(); | ||
this._keyboardWillHideSubscription.remove(); | ||
}; | ||
|
||
_configureLayoutAnimation = () => { | ||
// Any duration is OK here. The `type: 'keyboard defines the animation. | ||
LayoutAnimation.configureNext({ | ||
duration: 100, | ||
update: { | ||
type: 'keyboard', | ||
} | ||
}); | ||
} | ||
|
||
_keyboardWillShow = (e: any) => { | ||
this._configureLayoutAnimation(); | ||
this.setState({ | ||
keyboardHeight: e.endCoordinates.height - (this.props.offset || 0), | ||
}); | ||
}; | ||
|
||
_keyboardWillHide = () => { | ||
this._configureLayoutAnimation(); | ||
this.setState({ | ||
keyboardHeight: 0, | ||
}); | ||
}; | ||
|
||
render() { | ||
return <View style={{ height: this.state.keyboardHeight }} />; | ||
} | ||
} | ||
|
||
export default KeyboardSpacer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React, { Component } from 'react'; | ||
import { | ||
Platform, | ||
StyleSheet, | ||
Text, | ||
TouchableHighlight, | ||
TouchableNativeFeedback, | ||
View, | ||
} from 'react-native'; | ||
|
||
/** | ||
* Renders the right type of Touchable for the list item, based on platform. | ||
*/ | ||
const Touchable = ({onPress, children}) => { | ||
const child = React.Children.only(children); | ||
if (Platform.OS === 'android') { | ||
return ( | ||
<TouchableNativeFeedback onPress={onPress}> | ||
{child} | ||
</TouchableNativeFeedback> | ||
); | ||
} else { | ||
return ( | ||
<TouchableHighlight onPress={onPress} underlayColor='#ddd'> | ||
{child} | ||
</TouchableHighlight> | ||
); | ||
} | ||
} | ||
|
||
const ListItem = ({label, onPress}) => ( | ||
<Touchable onPress={onPress}> | ||
<View style={styles.item}> | ||
<Text style={styles.label}>{label}</Text> | ||
</View> | ||
</Touchable> | ||
); | ||
|
||
const styles = StyleSheet.create({ | ||
item: { | ||
height: 48, | ||
justifyContent: 'center', | ||
paddingLeft: 12, | ||
borderBottomWidth: StyleSheet.hairlineWidth, | ||
borderBottomColor: '#ddd', | ||
}, | ||
label: { | ||
fontSize: 16, | ||
} | ||
}); | ||
|
||
export default ListItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { AppRegistry } from 'react-native'; | ||
|
||
import MainNavigator from './views/MainNavigator'; | ||
|
||
AppRegistry.registerComponent('ChatExample', () => MainNavigator); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { AppRegistry } from 'react-native'; | ||
|
||
import MainNavigator from './views/MainNavigator'; | ||
|
||
AppRegistry.registerComponent('ChatExample', () => MainNavigator); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React, { Component } from 'react'; | ||
import { | ||
ListView, | ||
Platform, | ||
Text, | ||
} from 'react-native'; | ||
import { TabNavigator } from 'react-navigation'; | ||
|
||
import ChatListScreen from './chat/ChatListScreen'; | ||
import FriendListScreen from './friends/FriendListScreen'; | ||
|
||
/** | ||
* Screen with tabs shown on app startup. | ||
*/ | ||
const HomeScreenTabNavigator = TabNavigator({ | ||
Chats: { | ||
screen: ChatListScreen, | ||
}, | ||
Friends: { | ||
screen: FriendListScreen, | ||
}, | ||
}); | ||
|
||
export default HomeScreenTabNavigator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* This is an example React Native app demonstrates ListViews, text input and | ||
* navigation between a few screens. | ||
* https://github.com/facebook/react-native | ||
*/ | ||
|
||
import React, { Component } from 'react'; | ||
import { StackNavigator } from 'react-navigation'; | ||
|
||
import HomeScreenTabNavigator from './HomeScreenTabNavigator'; | ||
import ChatScreen from './chat/ChatScreen'; | ||
|
||
/** | ||
* Top-level navigator. Renders the application UI. | ||
*/ | ||
const MainNavigator = StackNavigator({ | ||
Home: { | ||
screen: HomeScreenTabNavigator, | ||
}, | ||
Chat: { | ||
screen: ChatScreen, | ||
}, | ||
}); | ||
|
||
export default MainNavigator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React, { Component } from 'react'; | ||
import { | ||
Image, | ||
ListView, | ||
Platform, | ||
StyleSheet, | ||
} from 'react-native'; | ||
import ListItem from '../../components/ListItem'; | ||
|
||
export default class ChatListScreen extends Component { | ||
|
||
static navigationOptions = { | ||
title: 'Chats', | ||
header: { | ||
visible: Platform.OS === 'ios', | ||
}, | ||
tabBar: { | ||
icon: ({ tintColor }) => ( | ||
<Image | ||
// Using react-native-vector-icons works here too | ||
source={require('./chat-icon.png')} | ||
style={[styles.icon, {tintColor: tintColor}]} | ||
/> | ||
), | ||
}, | ||
} | ||
|
||
constructor(props) { | ||
super(props); | ||
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); | ||
this.state = { | ||
dataSource: ds.cloneWithRows([ | ||
'Claire', 'John' | ||
]) | ||
}; | ||
} | ||
|
||
// Binding the function so it can be passed to ListView below | ||
// and 'this' works properly inside _renderRow | ||
_renderRow = (name) => { | ||
return ( | ||
<ListItem | ||
label={name} | ||
onPress={() => this.props.navigation.navigate('Chat', {name: name})} | ||
/> | ||
) | ||
} | ||
|
||
render() { | ||
return ( | ||
<ListView | ||
dataSource={this.state.dataSource} | ||
renderRow={this._renderRow} | ||
style={styles.listView} | ||
/> | ||
); | ||
} | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
listView: { | ||
backgroundColor: 'white', | ||
}, | ||
icon: { | ||
width: 30, | ||
height: 26, | ||
}, | ||
}); |
Oops, something went wrong.