Instantly share code, notes, and snippets.
Last active
May 9, 2016 12:12
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save sylvainbaronnet/3dcd34832466abe7be012d9f67d824d5 to your computer and use it in GitHub Desktop.
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
/** | |
* Copyright (c) 2015, Facebook, Inc. All rights reserved. | |
* | |
* Facebook, Inc. ("Facebook") owns all right, title and interest, including | |
* all intellectual property and other proprietary rights, in and to the React | |
* Native CustomComponents software (the "Software"). Subject to your | |
* compliance with these terms, you are hereby granted a non-exclusive, | |
* worldwide, royalty-free copyright license to (1) use and copy the Software; | |
* and (2) reproduce and distribute the Software as part of your own software | |
* ("Your Software"). Facebook reserves all rights not expressly granted to | |
* you in this license agreement. | |
* | |
* THE SOFTWARE AND DOCUMENTATION, IF ANY, ARE PROVIDED "AS IS" AND ANY EXPRESS | |
* OR IMPLIED WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE) ARE DISCLAIMED. | |
* IN NO EVENT SHALL FACEBOOK OR ITS AFFILIATES, OFFICERS, DIRECTORS OR | |
* EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE SOFTWARE, EVEN IF | |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* | |
*/ | |
import React, { | |
PropTypes, | |
} from 'react'; | |
import { | |
Platform, | |
Animated, | |
Image, | |
StyleSheet, | |
Text, | |
TouchableOpacity, | |
View, | |
} from 'react-native'; | |
import Actions from './Actions'; | |
import _drawerImage from './menu_burger.png'; | |
import _backButtonImage from './back_chevron.png'; | |
const styles = StyleSheet.create({ | |
title: { | |
textAlign: 'center', | |
marginTop: 10, | |
fontSize: 18, | |
fontWeight: '500', | |
color: '#0A0A0A', | |
position: 'absolute', | |
top: Platform.OS === 'ios' || Platform.Version > 19 ? 20 : 0, | |
left: 0, | |
right: 0, | |
}, | |
header: { | |
backgroundColor: '#EFEFF2', | |
paddingTop: 0, | |
top: 0, | |
height: Platform.OS === 'ios' || Platform.Version > 19 ? 64 : 44, | |
right: 0, | |
left: 0, | |
borderBottomWidth: 0.5, | |
borderBottomColor: '#828287', | |
position: 'absolute', | |
}, | |
backButton: { | |
width: 130, | |
height: 37, | |
position: 'absolute', | |
bottom: 4, | |
left: 2, | |
padding: 8, | |
flexDirection: 'row', | |
}, | |
rightButton: { | |
width: 100, | |
height: 37, | |
position: 'absolute', | |
bottom: 4, | |
right: 2, | |
padding: 8, | |
}, | |
leftButton: { | |
width: 100, | |
height: 37, | |
position: 'absolute', | |
bottom: 4, | |
left: 2, | |
padding: 8, | |
}, | |
barRightButtonText: { | |
color: 'rgb(0, 122, 255)', | |
textAlign: 'right', | |
fontSize: 17, | |
}, | |
barBackButtonText: { | |
color: 'rgb(0, 122, 255)', | |
textAlign: 'left', | |
fontSize: 17, | |
paddingLeft: 6, | |
}, | |
barLeftButtonText: { | |
color: 'rgb(0, 122, 255)', | |
textAlign: 'left', | |
fontSize: 17, | |
}, | |
backButtonImage: { | |
width: 13, | |
height: 21, | |
}, | |
rightButtonIconStyle: { | |
}, | |
}); | |
const propTypes = { | |
navigationState: PropTypes.object, | |
backButtonImage: PropTypes.number, | |
backButtonTextStyle: PropTypes.string, | |
leftButtonStyle: PropTypes.string, | |
leftButtonIconStyle: PropTypes.string, | |
getTitle: PropTypes.func, | |
titleStyle: PropTypes.object, | |
position: PropTypes.object, | |
navigationBarStyle: PropTypes.object, | |
}; | |
const contextTypes = { | |
drawer: PropTypes.object, | |
}; | |
const defaultProps = { | |
drawerImage: _drawerImage, | |
backButtonImage: _backButtonImage, | |
}; | |
class NavBar extends React.Component { | |
constructor(props) { | |
super(props); | |
this.renderRightButton = this.renderRightButton.bind(this); | |
this.renderBackButton = this.renderBackButton.bind(this); | |
this.renderLeftButton = this.renderLeftButton.bind(this); | |
this.renderTitle = this.renderTitle.bind(this); | |
} | |
renderBackButton() { | |
const state = this.props.navigationState; | |
const childState = state.children[state.index]; | |
let buttonImage = childState.backButtonImage || | |
state.backButtonImage || this.props.backButtonImage; | |
let onPress = Actions.pop; | |
if (state.index === 0) { | |
return null; | |
} | |
<<<<<<< HEAD | |
let text = childState.backTitle ? | |
<Text | |
style={[ | |
styles.barBackButtonText, | |
this.props.backButtonTextStyle, | |
state.backButtonTextStyle, | |
childState.backButtonTextStyle, | |
]} | |
> | |
{childState.backTitle} | |
</Text> | |
: null; | |
return ( | |
<TouchableOpacity | |
testID="backNavButton" | |
style={[ | |
styles.backButton, | |
this.props.leftButtonStyle, | |
state.leftButtonStyle, | |
childState.leftButtonStyle, | |
]} | |
onPress={onPress} | |
> | |
{buttonImage && | |
<Image | |
source={buttonImage} | |
style={[ | |
styles.backButtonImage, | |
this.props.leftButtonIconStyle, | |
state.barButtonIconStyle, | |
state.leftButtonIconStyle, | |
childState.leftButtonIconStyle, | |
]} | |
/> | |
======= | |
render() { | |
const state = this.props.navigationState; | |
const child = state.children[state.index]; | |
let selected = state.children[state.index]; | |
while (selected.hasOwnProperty("children")) { | |
selected = selected.children[selected.index] | |
} | |
if (state.navBar || selected.navBar){ | |
const Component = selected.navBar || state.navBar; | |
return <Component {...this.props} {...state} {...selected}/> | |
} | |
if (selected.component && selected.component.renderNavigationBar){ | |
return selected.component.renderNavigationBar({...this.props,...selected}); | |
} | |
if (child.hideNavBar || selected.hideNavBar) { | |
return null; | |
>>>>>>> origin/3.24 | |
} | |
{text} | |
</TouchableOpacity> | |
); | |
} | |
renderRightButton() { | |
const self = this; | |
function tryRender(state) { | |
if (state.rightButton) { | |
const Button = state.rightButton; | |
return ( | |
<<<<<<< HEAD | |
<Button | |
{...self.props} | |
{...state} | |
key={'rightNavBarBtn'} | |
testID="rightNavButton" | |
style={[styles.rightButton, state.rightButtonStyle]} | |
/> | |
======= | |
<Animated.View | |
style={[styles.header, state.navigationBarStyle, selected.navigationBarStyle]}> | |
{state.children.map(this._renderTitle, this)} | |
{renderLeftButton(selected) || renderBackButton(selected)} | |
{renderRightButton(selected)} | |
</Animated.View> | |
>>>>>>> origin/3.24 | |
); | |
} | |
if (state.onRight && (state.rightTitle || state.rightButtonImage)) { | |
const onPress = state.onRight.bind(null, state); | |
return ( | |
<TouchableOpacity | |
key={'rightNavBarBtn'} | |
testID="rightNavButton" | |
style={[styles.rightButton, state.rightButtonStyle]} | |
onPress={onPress} | |
> | |
{state.rightTitle && | |
<Text | |
style={[ | |
styles.barRightButtonText, | |
state.rightButtonTextStyle]} | |
> | |
{state.rightTitle} | |
</Text> | |
} | |
{state.rightButtonImage && | |
<View | |
style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-end' }} | |
> | |
<Image | |
source={state.rightButtonImage} | |
style={state.rightButtonIconStyle} | |
/> | |
</View>} | |
</TouchableOpacity> | |
); | |
} | |
if ((!!state.onRight ^ !!(state.rightTitle || state.rightButtonImage))) { | |
console.warn( | |
`Both onRight and rightTitle/rightButtonImage | |
must be specified for the scene: ${state.name}` | |
); | |
} | |
return null; | |
} | |
return tryRender(this.props); | |
} | |
renderLeftButton() { | |
const self = this; | |
const drawer = this.context.drawer; | |
function tryRender(state) { | |
let onPress = state.onLeft; | |
let buttonImage = state.leftButtonImage; | |
if (state.leftButton) { | |
const Button = state.leftButton; | |
return ( | |
<Button | |
{...self.props} | |
{...state} | |
key={'leftNavBarBtn'} | |
testID="leftNavButton" | |
style={[styles.leftButton, state.leftButtonStyle]} | |
/> | |
); | |
} | |
if (!!drawer && typeof drawer.toggle === 'function') { | |
buttonImage = state.drawerImage; | |
if (buttonImage) { | |
onPress = drawer.toggle; | |
} | |
} | |
if (onPress && (state.leftTitle || buttonImage)) { | |
onPress = onPress.bind(null, state); | |
return ( | |
<TouchableOpacity | |
key={'leftNavBarBtn'} | |
testID="leftNavButton" | |
style={[styles.leftButton, state.leftButtonStyle]} | |
onPress={onPress} | |
> | |
{state.leftTitle && | |
<Text | |
style={[ | |
styles.barLeftButtonText, | |
state.leftButtonTextStyle, | |
]} | |
> | |
{state.leftTitle} | |
</Text> | |
} | |
{buttonImage && | |
<View | |
style={{ flex: 1, justifyContent: 'center', alignItems: 'flex-start' }} | |
> | |
<Image | |
source={buttonImage} | |
style={state.leftButtonIconStyle} | |
/> | |
</View>} | |
</TouchableOpacity> | |
); | |
} | |
if ((!!state.onLeft ^ !!(state.leftTitle || buttonImage))) { | |
console.warn( | |
`Both onLeft and leftTitle/leftButtonImage | |
must be specified for the scene: ${state.name}` | |
); | |
} | |
return null; | |
} | |
return tryRender(this.props); | |
} | |
<<<<<<< HEAD | |
renderTitle(childState, index:number) { | |
const title = this.props.getTitle ? this.props.getTitle(childState) : childState.title; | |
return ( | |
<Animated.Text | |
key={childState.key} | |
style={[ | |
styles.title, | |
this.props.titleStyle, | |
this.props.navigationState.titleStyle, | |
childState.titleStyle, | |
======= | |
_renderTitle(childState: NavigationState, index:number) { | |
const title = childState.renderTitle ? | |
childState.renderTitle():this.props.getTitle ? this.props.getTitle(childState) : childState.title; | |
return ( | |
<Animated.Text | |
key={childState.key} | |
style={[ | |
styles.title, this.props.navigationState.titleStyle, childState.titleStyle, | |
>>>>>>> origin/3.24 | |
{ | |
opacity: this.props.position.interpolate({ | |
inputRange: [index - 1, index, index + 1], | |
outputRange: [0, 1, 0], | |
}), | |
left: this.props.position.interpolate({ | |
inputRange: [index - 1, index + 1], | |
outputRange: [200, -200], | |
}), | |
right: this.props.position.interpolate({ | |
inputRange: [index - 1, index + 1], | |
outputRange: [-200, 200], | |
}), | |
}, | |
<<<<<<< HEAD | |
]} | |
> | |
{title} | |
</Animated.Text> | |
); | |
} | |
render() { | |
let state = this.props.navigationState; | |
let selected = state.children[state.index]; | |
while (selected.hasOwnProperty('children')) { | |
state = selected; | |
selected = selected.children[selected.index]; | |
======= | |
]}> | |
{title} | |
</Animated.Text> | |
); | |
>>>>>>> origin/3.24 | |
} | |
const renderLeftButton = selected.renderLeftButton || | |
selected.component.renderLeftButton || | |
this.renderLeftButton; | |
const renderRightButton = selected.renderRightButton || | |
selected.component.renderRightButton || | |
this.renderRightButton; | |
const renderBackButton = selected.renderBackButton || | |
selected.component.renderBackButton || | |
this.renderBackButton; | |
const renderTitle = selected.renderTitle || | |
selected.component.renderTitle || | |
this.props.renderTitle; | |
return ( | |
<Animated.View | |
style={[ | |
styles.header, | |
this.props.navigationBarStyle, | |
state.navigationBarStyle, | |
selected.navigationBarStyle, | |
]} | |
> | |
{renderTitle ? renderTitle(selected) : state.children.map(this.renderTitle, this)} | |
{renderBackButton() || renderLeftButton()} | |
{renderRightButton()} | |
</Animated.View> | |
); | |
} | |
} | |
NavBar.propTypes = propTypes; | |
NavBar.contextTypes = contextTypes; | |
NavBar.defaultProps = defaultProps; | |
export default NavBar; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment