diff --git a/AppIntro.js b/AppIntro.js index 7ea6ad6..52b42d9 100644 --- a/AppIntro.js +++ b/AppIntro.js @@ -1,6 +1,7 @@ import assign from 'assign-deep'; import React, { Component, PropTypes } from 'react'; import { + StatusBar, StyleSheet, Text, View, @@ -240,7 +241,7 @@ export default class AppIntro extends Component { const AnimatedStyle1 = this.getTransform(index, 10, level); const AnimatedStyle2 = this.getTransform(index, 0, level); const AnimatedStyle3 = this.getTransform(index, 15, level); - const imgSource = (typeof img === 'string') ? {uri: img} : img; + const imgSource = (typeof img === 'string') ? {uri: img} : img; const pageView = ( @@ -284,6 +285,22 @@ export default class AppIntro extends Component { return animatedChild; } + shadeStatusBarColor(color, percent) { + const first = parseInt(color.slice(1), 16); + const black = first & 0x0000FF; + const green = first >> 8 & 0x00FF; + const percentage = percent < 0 ? percent * -1 : percent; + const red = first >> 16; + const theme = percent < 0 ? 0 : 255; + const finalColor = (0x1000000 + (Math.round((theme - red) * percentage) + red) * 0x10000 + (Math.round((theme - green) * percentage) + green) * 0x100 + (Math.round((theme - black) * percentage) + black)).toString(16).slice(1); + + return `#${finalColor}`; + } + + isToTintStatusBar() { + return this.props.pageArray && this.props.pageArray.length > 0 && Platform.OS === 'android' + } + render() { const childrens = this.props.children; const { pageArray } = this.props; @@ -314,6 +331,11 @@ export default class AppIntro extends Component { }); } } + + if (this.isToTintStatusBar()) { + StatusBar.setBackgroundColor(this.shadeStatusBarColor(this.props.pageArray[0].backgroundColor, -0.3), false); + } + return ( {androidPages} @@ -322,6 +344,10 @@ export default class AppIntro extends Component { index={this.props.defaultIndex} renderPagination={this.renderPagination} onMomentumScrollEnd={(e, state) => { + if (this.isToTintStatusBar()) { + StatusBar.setBackgroundColor(this.shadeStatusBarColor(this.props.pageArray[state.index].backgroundColor, -0.3), false); + } + this.props.onSlideChange(state.index, state.total); }} onScroll={Animated.event( diff --git a/Example/AppIntro.js b/Example/AppIntro.js index dc8dc31..52b42d9 100644 --- a/Example/AppIntro.js +++ b/Example/AppIntro.js @@ -1,6 +1,7 @@ import assign from 'assign-deep'; import React, { Component, PropTypes } from 'react'; import { + StatusBar, StyleSheet, Text, View, @@ -11,6 +12,10 @@ import { Platform, } from 'react-native'; import Swiper from 'react-native-swiper'; +import DoneButton from './components/DoneButton'; +import SkipButton from './components/SkipButton'; +import RenderDots from './components/Dots'; + const windowsWidth = Dimensions.get('window').width; const windowsHeight = Dimensions.get('window').height; @@ -62,13 +67,6 @@ const defaulStyles = { }, activeDotStyle: { backgroundColor: '#fff', - width: 13, - height: 13, - borderRadius: 7, - marginLeft: 7, - marginRight: 7, - marginTop: 7, - marginBottom: 7, }, paginationContainer: { position: 'absolute', @@ -189,21 +187,6 @@ export default class AppIntro extends Component { } renderPagination = (index, total, context) => { - const { activeDotColor, dotColor, rightTextColor, leftTextColor } = this.props; - const ActiveDot = ( - - ); - const Dot = ; - let dots = []; - for (let i = 0; i < total; i++) { - dots.push(i === index ? - React.cloneElement(ActiveDot, { key: i }) - : - React.cloneElement(Dot, { key: i }) - ); - } let isDoneBtnShow; let isSkipBtnShow; if (index === total - 1) { @@ -219,91 +202,31 @@ export default class AppIntro extends Component { isDoneBtnShow = false; isSkipBtnShow = true; } - let controllBts; - if (Platform.OS === 'ios') { - controllBts = ( - - - this.props.onSkipBtnClick(index) : null} - > - {this.props.skipBtnLabel} - - - - {dots} - - - - - {this.props.doneBtnLabel} - - - - - {this.props.nextBtnLabel} - - - - - ); - } else { - controllBts = ( - - - this.props.onSkipBtnClick(index) : null} - > - {this.props.skipBtnLabel} - - - - {dots} - - - - - {isDoneBtnShow ? this.props.doneBtnLabel : this.props.nextBtnLabel} - - - - - ); - } - return controllBts; + return ( + + {this.props.showSkipButton ? this.props.onSkipBtnClick(index)} /> : + + } + {this.props.showDots && RenderDots(index, total, { + ...this.props, + styles: this.styles + })} + {this.props.showDoneButton ? : + + } + + ); } renderBasicSlidePage = (index, { @@ -318,10 +241,11 @@ export default class AppIntro extends Component { const AnimatedStyle1 = this.getTransform(index, 10, level); const AnimatedStyle2 = this.getTransform(index, 0, level); const AnimatedStyle3 = this.getTransform(index, 15, level); + const imgSource = (typeof img === 'string') ? {uri: img} : img; const pageView = ( - + @@ -361,6 +285,22 @@ export default class AppIntro extends Component { return animatedChild; } + shadeStatusBarColor(color, percent) { + const first = parseInt(color.slice(1), 16); + const black = first & 0x0000FF; + const green = first >> 8 & 0x00FF; + const percentage = percent < 0 ? percent * -1 : percent; + const red = first >> 16; + const theme = percent < 0 ? 0 : 255; + const finalColor = (0x1000000 + (Math.round((theme - red) * percentage) + red) * 0x10000 + (Math.round((theme - green) * percentage) + green) * 0x100 + (Math.round((theme - black) * percentage) + black)).toString(16).slice(1); + + return `#${finalColor}`; + } + + isToTintStatusBar() { + return this.props.pageArray && this.props.pageArray.length > 0 && Platform.OS === 'android' + } + render() { const childrens = this.props.children; const { pageArray } = this.props; @@ -391,13 +331,23 @@ export default class AppIntro extends Component { }); } } + + if (this.isToTintStatusBar()) { + StatusBar.setBackgroundColor(this.shadeStatusBarColor(this.props.pageArray[0].backgroundColor, -0.3), false); + } + return ( {androidPages} { + if (this.isToTintStatusBar()) { + StatusBar.setBackgroundColor(this.shadeStatusBarColor(this.props.pageArray[state.index].backgroundColor, -0.3), false); + } + this.props.onSlideChange(state.index, state.total); }} onScroll={Animated.event( @@ -434,6 +384,10 @@ AppIntro.propTypes = { PropTypes.element, ]), customStyles: PropTypes.object, + defaultIndex: PropTypes.number, + showSkipButton: PropTypes.bool, + showDoneButton: PropTypes.bool, + showDots: PropTypes.bool, }; AppIntro.defaultProps = { @@ -449,4 +403,8 @@ AppIntro.defaultProps = { doneBtnLabel: 'Done', skipBtnLabel: 'Skip', nextBtnLabel: '›', + defaultIndex: 0, + showSkipButton: true, + showDoneButton: true, + showDots: true }; diff --git a/README.md b/README.md index 5bf9eed..b9b9eb5 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,12 @@ $ npm i react-native-app-intro --save ### Basic Usage -You can use pageArray quick generation your app intro with parallax effect. +You can use pageArray quick generation your app intro with parallax effect. With the basic usage, the Android status bar will be updated to match your slide background color. + + ```javascript import React, { Component } from 'react'; import { AppRegistry, Alert } from 'react-native'; diff --git a/assets/sample-android.gif b/assets/sample-android.gif new file mode 100644 index 0000000..c52f421 Binary files /dev/null and b/assets/sample-android.gif differ