- 准备:
react-native init banner
cd xxxxx/banner
react-native run-android
在RN里面实现轮播广告banner滚动条主要是用ScrollView来实现,首先看下ScrollView的用法:
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}>
{this.renderScrollView()}
</ScrollView>
renderScrollView = () => {
return colors.map((item, i) => {
return <Image key={item+i} style={styles.imageStyle} source={require('./image/img_01.png')}></Image>
})
}
这里引用了ScrollView,里面的子控件通过一个数组的map来获得,通常在我们的项目中banner的条目的个数是从服务器获取,根据返回的数据的列表的个数来知道banner滚动的个数,这里只是用color数组模拟了的数据,返回的是color数组长度的Image图片控件,作为最简单的banner实现。
代码说明:
- horizontal属性控制ScrollView的滚动方向
-
pagingEnable 控制ScrollViewm每次滚动是否滚动一个子控件的距离,为true,则和Android的ViewPager的效果一致,每次滚动一页,为false,则为普通的ScrollView的效果。
绘制圆点:
//绘制圆点
renderCircle = ()=> {
return colors.map((item,i) => {
return <Text key={`item${i}`} style={styles.circleStyle}>•</Text>
})
}
render() {
return <View style={styles.container}>
<ScrollView
horizontal={true}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}>
{this.renderScrollView()}
</ScrollView>
<View style={styles.circleWrapperStyle}>
{this.renderCircle()}
</View>
</View>
}
var styles = StyleSheet.create({
container :{
flexDirection:'column'
},
imageStyle: {
width: screenWidth,
height: 140
},
circleStyle: {
fontSize:20,
color:'red'
},
circleWrapperStyle: {
flexDirection:'row',
bottom:0,
left:10,
position:'absolute'
}
})
- 首先绘制圆点是用html的特殊文字代替,html的特殊字符编码对照表:http://www.jb51.net/onlineread/htmlchar.htm,里面的圆对应的编码为"bull;"
-
其次,圆点的绝对布局,当最外层布局container的flexDirection:'column'的时候是相当于Android的LinearLayout的布局一样,不会悬浮在图片之上,必须制定其position:'absolute'为绝对布局,意思是相对父容器的绝对位置,bottom:0,将其设置在底部,这样才大功告成。
绘制不同颜色的点
//绘制圆点
renderCircle = ()=> {
return colors.map((item,i) => {
var style = {};
if(i === 0) {
style = {color:'orange'};
}
return <Text key={`item${i}`} style={[styles.circleStyle,style]}>•</Text>
})
}
要点:
在react组件里面如果有多个属性对象,则用数组表示,后面的属性则会覆盖前面的属性
ScrollView的onScroll回调方法:
在滚动的过程中,每帧最多调用一次此回调函数。调用的频率可以用scrollEventThrottle属性来控制。我们可以利用这个回调来计算当前滑到了第几页从而改变圆点的位置。
<ScrollView
horizontal={true}
pagingEnabled={true}
onScroll={this.handleScroll}
showsHorizontalScrollIndicator={false}>
{this.renderScrollView()}
</ScrollView>
handleScroll = (e)=> {
var x = e.nativeEvent.contentOffset.x;
if(x%screenWidth === 0) {
this.setState({currentPage:x/screenWidth});
}
}
//绘制圆点
renderCircle = ()=> {
return colors.map((item,i) => {
var style = {};
if(i === this.state.currentPage) {
style = {color:'orange'};
}
return <Text key={`item${i}`} style={[styles.circleStyle,style]}>•</Text>
})
}
- onScroll回调函数中会传入一个事件的参数e,e.nativeEvent.contentOffset.x表示当前滑动了多少像素,因此可以计算出当前是滑到第几页,从而改变state,重绘圆点。
- 还可以利用onMomentumScrollBegin属性来完成,这里相当于viewpager的onPageSelected,而onScroll相当于onPageScroll();
自动滚动
自动滚动需要一个定时器,再通过调用ScrollView.scrollTo();方法来实现滚动
定时器在componentDidMount()里面启动。
startTimer = ()=>{
setInterval(()=>{
var currentPage = ++this.state.currentPage==4?0:this.state.currentPage
this.refs.scrollview.scrollTo({x:currentPage*screenWidth,y:0,animated: true})
},2000)
}
- 最后呢,处理定时器于手动滑动的冲突
ScrollView的开始拖拽和停止拖拽会回调onScrollBeginDrag、onScrollEndDrag的属性的传值方法,可以在里面控制停止定时器和开启定时器
onScrollBeginDrag={this.handleScrollBegin}
onScrollEndDrag={this.handleScrollEnd}
//开始拖拽
handleScrollBegin=()=> {
clearInterval(this.timmer)
}
//停止拖拽
handleScrollEnd=()=> {
this.startTimer();
}