Last active
October 18, 2016 12:14
-
-
Save gabecoyne/3b9ffa89b07ac4f42dc7 to your computer and use it in GitHub Desktop.
React Native Android ViewPager
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
'use-strict' | |
var React = require('react-native'); | |
var { | |
Dimensions | |
} = React; | |
var DimensionsHelper = { | |
init : function() { | |
this.SCREEN_WIDTH = Dimensions.get("window").width; | |
this.SCREEN_HEIGHT = Dimensions.get("window").height; | |
} | |
} | |
DimensionsHelper.init(); | |
module.exports = DimensionsHelper |
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
'use strict'; | |
var React = require('react-native'); | |
var { | |
View, | |
ViewPagerAndroid, | |
Text | |
} = React; | |
var ViewPagerTabs = require("./ViewPagerTabs"); | |
var ViewPagerDots = require("./ViewPagerDots"); | |
var DimensionsHelper = require("./DimensionsHelper"); | |
var ViewPager = React.createClass({ | |
componentDidMount: function(){ | |
console.log("ViewPager componentDidMount"); | |
}, | |
getDefaultProps: function(){ | |
}, | |
getInitialState: function(){ | |
return { | |
activeTab:0 | |
} | |
}, | |
goToPage: function(page){ | |
this.setState({activeTab: page}); | |
}, | |
onPageScroll: function(e){ | |
this.tabs.onPageScroll(e); | |
}, | |
onPageSelected: function(e){ | |
this.tabs.onPageSelected(e); | |
}, | |
renderTabBar() { | |
if (this.props.bar === 'tabs') { | |
return <ViewPagerTabs children={this.props.children} viewPager={() => {return this.viewPager}} ref={(comp) => {this.tabs = comp}} />;; | |
} else { | |
return <ViewPagerDots children={this.props.children} viewPager={() => {return this.viewPager}} ref={(comp) => {this.tabs = comp}} />;; | |
} | |
}, | |
render() { | |
return ( | |
<View> | |
{this.props.position == 'top' ? this.renderTabBar() : null} | |
<ViewPagerAndroid ref={(comp) => {this.viewPager = comp}} | |
onPageScroll={this.onPageScroll} | |
onPageSelected={this.onPageSelected} | |
style={{ | |
flexDirection:'row', | |
backgroundColor:'#ccc', | |
height: this.props.height || 300, | |
width: this.props.width || DimensionsHelper.SCREEN_WIDTH | |
}} | |
> | |
{this.props.children} | |
</ViewPagerAndroid> | |
{this.props.position == 'bottom' ? this.renderTabBar() : null} | |
</View> | |
); | |
} | |
}); | |
module.exports = ViewPager; |
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
'use strict'; | |
var React = require('react-native'); | |
var { | |
View, | |
Text, | |
ViewPagerAndroid, | |
StyleSheet, | |
TouchableOpacity | |
} = React; | |
var DimensionsHelper = require("./DimensionsHelper"); | |
var ViewPagerDots = React.createClass({ | |
getDefaultProps: function(){ | |
}, | |
getInitialState: function(){ | |
return { activeTab:0 } | |
}, | |
// called from ViewPager | |
onPageScroll: function(e){ | |
this.setState({random:1}) | |
}, | |
// called from ViewPager | |
onPageSelected: function(e){ | |
this.setState({activeTab: e.nativeEvent.position}); | |
}, | |
// goto(2) | |
goToPage: function(page){ | |
console.log("goToPage", page); | |
this.props.viewPager().setPage(page); | |
this.setState({activeTab: page}); | |
}, | |
renderTab(child, page){ | |
var isTabActive = this.state.activeTab === page; | |
return ( | |
<TouchableOpacity onPress={() => this.goToPage(page)}> | |
<View style={[styles.dot, (isTabActive ? styles.active : styles.inactive)]} /> | |
</TouchableOpacity> | |
) | |
}, | |
render() { | |
return ( | |
<View style={styles.dots} {...this.props}> | |
{this.props.children.map((child, i) => this.renderTab(child, i))} | |
</View> | |
); | |
} | |
}); | |
var styles = StyleSheet.create({ | |
dots: { | |
height:40, | |
flex:1, | |
flexDirection: 'row', | |
alignItems:'center', | |
justifyContent: 'center' | |
}, | |
dot: { | |
width: 10, | |
height: 10, | |
marginHorizontal: 3, | |
borderRadius: 5, | |
borderWidth: 1, | |
borderColor: "#ccc", | |
backgroundColor: "#fff" | |
}, | |
active: { | |
backgroundColor: "#ccc" | |
}, | |
intactive: { | |
backgroundColor: "#fff" | |
} | |
}); | |
module.exports = ViewPagerDots; |
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
'use strict'; | |
var React = require('react-native'); | |
var { | |
View, | |
Text, | |
ViewPagerAndroid, | |
StyleSheet, | |
TouchableOpacity | |
} = React; | |
var DimensionsHelper = require("./DimensionsHelper"); | |
var ViewPagerTabs = React.createClass({ | |
getDefaultProps: function(){ | |
}, | |
getInitialState: function(){ | |
return { | |
activeTab:0, | |
left: 0 | |
} | |
}, | |
moveActiveLine:function(e){ | |
console.log("ViewPagerTabs.moveActiveLine", e.nativeEvent); | |
var width = DimensionsHelper.SCREEN_WIDTH | |
var tabWidth = width / this.props.children.length; | |
var left = (tabWidth * (e.nativeEvent.offset || 0)) + (tabWidth * e.nativeEvent.position); | |
if(!e.nativeEvent.position || left) this.setState({left: left}); | |
}, | |
// called from ViewPager | |
onPageScroll: function(e){ | |
this.moveActiveLine(e); | |
}, | |
// called from ViewPager | |
onPageSelected: function(e){ | |
// this.moveActiveLine(e); | |
this.setState({activeTab: e.nativeEvent.position}); | |
}, | |
// goto(2) | |
goToPage: function(page){ | |
console.log("goToPage", page); | |
this.props.viewPager().setPage(page); | |
this.setState({activeTab: page}); | |
}, | |
renderTab(child, page){ | |
var isTabActive = this.state.activeTab === page; | |
var textStyle = { | |
color: isTabActive ? '#666' : '#999', | |
fontWeight: isTabActive ? 'bold' : 'normal' | |
} | |
return ( | |
<TouchableOpacity | |
style={[ | |
styles.tab, | |
{width: DimensionsHelper.SCREEN_WIDTH/this.props.children.length}]} | |
onPress={() => this.goToPage(page)}> | |
<View> | |
<Text style={textStyle}>{child.props.tabLabel}</Text> | |
</View> | |
</TouchableOpacity> | |
) | |
}, | |
render() { | |
return ( | |
<View style={styles.tabs} {...this.props}> | |
{this.props.children.map((child, i) => this.renderTab(child, i))} | |
<View | |
ref={(comp) => {this.activeLine = comp}} | |
style={[styles.activeLine, {left: this.state.left, width: DimensionsHelper.SCREEN_WIDTH/this.props.children.length}]} /> | |
</View> | |
); | |
} | |
}); | |
var styles = StyleSheet.create({ | |
tabs:{ | |
flex: 1, | |
flexDirection: 'row', | |
alignItems: 'center', | |
borderBottomWidth: 1, | |
borderColor: '#eee' | |
}, | |
tab:{ | |
height: 45, | |
paddingBottom: 5, | |
justifyContent: 'center', | |
alignItems: 'center' | |
}, | |
activeLine:{ | |
height: 4, | |
backgroundColor: '#999', | |
position:'absolute', | |
top: 42, | |
left: 0 | |
} | |
}) | |
module.exports = ViewPagerTabs; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great gist, but it seems to me that passing children with content to tab/dot navigation might cause poor performance. For example, if there is a long list in each tab.