1 Star 0 Fork 0

hanwenbo/react-native-app-intro-slider

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
AppIntroSlider.js 7.04 KB
一键复制 编辑 原始数据 按行查看 历史
李杰 提交于 7年前 . Update AppIntroSlider.js
import React from 'react';
import {
StyleSheet,
FlatList,
View,
Dimensions,
Text,
TouchableOpacity,
Platform,
StatusBar,
} from 'react-native';
import DefaultSlide from './DefaultSlide';
const { width, height } = Dimensions.get('window');
const isIphoneX = (
Platform.OS === 'ios' &&
!Platform.isPad &&
!Platform.isTVOS &&
(height === 812 || width === 812)
);
export default class AppIntroSlider extends React.Component {
static defaultProps = {
activeDotColor: 'rgba(255, 255, 255, .9)',
dotColor: 'rgba(0, 0, 0, .2)',
skipLabel: 'Skip',
doneLabel: 'Done',
nextLabel: 'Next',
prevLabel: 'Back',
}
state = {
width,
height,
activeIndex: 0,
};
goToSlide = (pageNum) => {
this.setState({ activeIndex: pageNum });
this.flatList.scrollToOffset({ offset: pageNum * this.state.width });
}
_onNextPress = () => {
this.goToSlide(this.state.activeIndex + 1);
this.props.onSlideChange && this.props.onSlideChange(this.state.activeIndex + 1, this.state.activeIndex);
}
_onPrevPress = () => {
this.goToSlide(this.state.activeIndex - 1);
this.props.onSlideChange && this.props.onSlideChange(this.state.activeIndex - 1, this.state.activeIndex);
}
_renderItem = (item) => {
const { width, height } = this.state;
const bottomSpacer = (this.props.bottomButton ? (this.props.showSkipButton ? 44 : 0) + 44 : 0) + (isIphoneX ? 34 : 0) + 64;
const topSpacer = (isIphoneX ? 44 : 0) + (Platform.OS === 'ios' ? 20 : StatusBar.currentHeight);
const props = { ...item.item, bottomSpacer, topSpacer, width, height };
return this.props.renderItem ? this.props.renderItem(props) : <DefaultSlide {...props} />;
}
_renderButton = (name, onPress) => {
const show = (name === 'Skip' ||  name === 'Prev') ? this.props[`show${name}Button`] : !this.props[`hide${name}Button`];
const content = this.props[`render${name}Button`] ? this.props[`render${name}Button`]() : this._renderDefaultButton(name);
return show && this._renderOuterButton(content, name, onPress);
}
_renderDefaultButton = (name) => {
let content = <Text style={styles.buttonText}>{this.props[`${name.toLowerCase()}Label`]}</Text>;
if (this.props.bottomButton) {
content = <View style={[styles.bottomButton, (name === 'Skip' || name === 'Prev') && { backgroundColor: 'transparent' }]}>{content}</View>
}
return content;
}
_renderOuterButton = (content, name, onPress) => {
const style = (name === 'Skip' ||  name === 'Prev') ? styles.leftButtonContainer : styles.rightButtonContainer;
return (
<View style={this.props.bottomButton ? styles.bottomButtonContainer : style}>
<TouchableOpacity onPress={onPress} style={[
this.props.bottomButton && styles.flexOne,
this.props.buttonStyle
]}>
{content}
</TouchableOpacity>
</View>
)
}
_renderNextButton = () => this._renderButton('Next', this._onNextPress)
_renderPrevButton = () => this._renderButton('Prev', this._onPrevPress)
_renderDoneButton = () => this._renderButton('Done', this.props.onDone && this.props.onDone)
_renderSkipButton = () => this._renderButton('Skip', this.props.onSkip && this.props.onSkip)
_renderPagination = () => {
const isLastSlide = this.state.activeIndex === (this.props.slides.length - 1);
const btn = isLastSlide ? this._renderDoneButton() : this._renderNextButton();
return (
<View style={styles.paginationContainer}>
<View style={styles.paginationDots}>
{this.props.slides.length > 1 && this.props.slides.map((_, i) => (
<View
key={i}
style={[
{ backgroundColor: i === this.state.activeIndex ? this.props.activeDotColor : this.props.dotColor },
styles.dot,
]}
/>
))}
{/* {!this.props.bottomButton && btn} */}
</View>
</View>
)
}
_renderViewButton = () => {
const isLastSlide = this.state.activeIndex === (this.props.slides.length - 1);
const isFirstSlide = this.state.activeIndex === 0;
const skipBtn = (!isFirstSlide && this._renderPrevButton()) || (!isLastSlide && this._renderSkipButton());
const btn = isLastSlide ? this._renderDoneButton() : this._renderNextButton();
if (this.props.bottomButton) {
return skipBtn
} else {
return null
}
}
_onMomentumScrollEnd = (e) => {
const offset = e.nativeEvent.contentOffset.x;
// Touching very very quickly and continuous brings about
// a variation close to - but not quite - the width.
// That's why we round the number.
// Also, Android phones and their weird numbers
const newIndex = Math.round(offset / this.state.width);
if (newIndex === this.state.activeIndex) {
// No page change, don't do anything
return;
}
const lastIndex = this.state.activeIndex;
this.setState({ activeIndex: newIndex });
this.props.onSlideChange && this.props.onSlideChange(newIndex, lastIndex);
}
_onLayout = () => {
const { width, height } = Dimensions.get('window');
if (width !== this.state.width || height !== this.state.height) {
// Set new width to update rendering of pages
this.setState({ width, height });
// Set new scroll position
const func = () => { this.flatList.scrollToOffset({ offset: this.state.activeIndex * width, animated: false }) }
Platform.OS === 'android' ? setTimeout(func, 0) : func();
}
}
render() {
const isLastSlide = this.state.activeIndex === (this.props.slides.length - 1);
const btn = isLastSlide ? this._renderDoneButton() : this._renderNextButton();
return (
<View style={styles.flexOne}>
<FlatList
ref={ref => this.flatList = ref}
data={this.props.slides}
horizontal
pagingEnabled
showsHorizontalScrollIndicator={false}
bounces={false}
style={styles.flexOne}
renderItem={this._renderItem}
onMomentumScrollEnd={this._onMomentumScrollEnd}
extraData={this.state.width}
onLayout={this._onLayout}
/>
{this._renderPagination()}
{!this.props.bottomButton && btn}
</View>
);
}
}
const styles = StyleSheet.create({
flexOne: {
flex: 1,
},
paginationContainer: {
position: 'absolute',
bottom: 16 + (isIphoneX ? 34 : 0),
left: 0,
right: 0,
},
paginationDots: {
height: 16,
margin: 16,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
},
dot: {
width: 10,
height: 10,
borderRadius: 5,
marginHorizontal: 4,
},
leftButtonContainer: {
position: 'absolute',
left: 0,
},
rightButtonContainer: {
position: 'absolute',
right: 0,
},
bottomButtonContainer: {
height: 44,
marginHorizontal: 16,
},
bottomButton: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, .3)',
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
backgroundColor: 'transparent',
color: 'white',
fontSize: 18,
padding: 16,
}
});
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/hanwenbo/react-native-app-intro-slider.git
git@gitee.com:hanwenbo/react-native-app-intro-slider.git
hanwenbo
react-native-app-intro-slider
react-native-app-intro-slider
master

搜索帮助