react native开发Android 篇——ScrollView和ViewPagerAndroid实现滑动翻页功能
- ScrollView使用PanResponder实现滑动和点击翻页
- ViewPagerAndroid滑动翻页和使用setPage点击翻页
详细代码可前往我在github上的demo查看。
ScrollView使用PanResponder实现滑动和点击翻页
onScrollBeginDrag
当用户开始拖动此视图时调用此函数。onScroll
在滚动的过程中,每帧最多调用一次此回调函数。调用的频率可以用scrollEventThrottle
属性来控制。onScrollEndDrag
当用户停止拖动此视图时调用此函数。scrollTo
滚动到指定的x, y偏移处。第三个参数为是否启用平滑滚动动画。还有一个duration
参数则是仅限android
可以使用的滚动持续时间。- 获取元素使用
ref
ScrollView.nativeEvent
返回的是一个对象,详细信息如下表所示:
属性 | Value |
responderIgnoreScroll | 类型是Boolean,作用暂时未知 |
target | 类型是number,接收触摸事件的元素id |
velocity | 类型是object,作用暂时未知eg:{ y: 0, x: 0 } |
layoutMeasurement | ScrollView可视区域的大小,eg:{ height: 491, width: 360 }表示491是ScrollView的高度,360是屏幕的宽度 |
contentSize | ScrollView的大小,eg:{ height: 491, width: 965 } |
contentOffset | 用来手动设置初始的滚动坐标。默认值为{x: 0, y: 0}。eg:{ y: 0, x: 303 }表示y轴不变,x轴向右移动303 |
contentInset | 内容范围相对滚动视图边缘的坐标。默认为{top: 0, left: 0, bottom: 0, right: 0}。 |
注意:使用ScrollView
自己的方法滚动会有惯性存在,可能会来回的滚动,所以在这里使用PanResponder
完成页面的翻转。
使用:
import React, {Component} from 'react';
import {Image, StyleSheet, Text, View,TouchableHighlight,Animated,ScrollView,Dimensions,PanResponder,YellowBox} from 'react-native';
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
pageArr:[require('../../src/images/1.jpg'),require('../../src/images/2.jpg'),require('../../src/images/3.jpg'),require('../../src/images/4.jpg'),require('../../src/images/5.jpg')],
swiperIndex:0,
screent_width:Dimensions.get('window').width,
ScrollView_contentOffset_before:0,
isLeft:false,
}
YellowBox.ignoreWarnings([//禁止componentWillMount和componentWillReceiveProps的黄色警告
'Warning: componentWillMount is deprecated',
'Warning: componentWillReceiveProps is deprecated',
]);
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => {},
onPanResponderGrant: (evt, gestureState) => {},
onPanResponderStart: (evt, gestureState) => {},
onPanResponderMove: (evt, gestureState) => {
let isLeft=false;
let touch_move=this.state.ScrollView_contentOffset_before;
let flag=true;
if (gestureState.dx > 0) {//右移
isLeft=false;
touch_move=touch_move-parseInt(gestureState.dx);
} else {
isLeft=true;
touch_move=touch_move+parseInt(Math.abs(gestureState.dx));
}
flag=this.isMove(this.state.swiperIndex,isLeft);;
if(flag){
this.refs.swiper_ScrollView.scrollTo({ x:touch_move, y: 0, animated: true }, 1);
}
this.setState({
isLeft:isLeft,
})
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
let flag=this.isMove(this.state.swiperIndex,this.state.isLeft);
if(flag){
this.ScrollView_move(true,0);
}
},
onPanResponderTerminate: (evt, gestureState) => {},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
});
}
isMove(index,isLeft){
let flag=true;
if(index==0&&isLeft){//是第一页则可以向左滑
flag=true;
}else if(index==0&&!isLeft){//是第一页则不可以右滑
flag=false;
}
if(index==this.state.pageArr.length-1&&isLeft){//是最后页则不能向左滑
flag=false;
}else if(index==this.state.pageArr.length-1&&!isLeft){//是第一页则可以右滑
flag=true;
}
return flag;
}
ScrollView_move(isDrag,index){//isDrag为true是滑动,为false是点击
var that = this;
let { pageArr, isLeft,ScrollView_contentOffset_before,screent_width } = that.state;
var swiperIndex=index;
isLeft=isDrag?isLeft:swiperIndex>this.state.swiperIndex?true:false;
var move_spacing= isLeft ? (screent_width) : (-screent_width);//每次移动多少
var move_width=ScrollView_contentOffset_before+ move_spacing;//ScrollView移动的距离
if(isDrag){
swiperIndex=Math.abs(Math.floor(move_width / move_spacing));
}else{//点击分页按钮
move_width=ScrollView_contentOffset_before+ move_spacing*Math.abs(index-this.state.swiperIndex);
}
that.refs.swiper_ScrollView.scrollTo({ x: move_width, y: 0, animated: true }, 1);
this.setState({
ScrollView_contentOffset_before:move_width,
swiperIndex:swiperIndex,
})
}
render() {
const {pageArr,swiperIndex,screent_width}=this.state;
return (
<View style={styles.container}>
<View style={styles.swiperContainer}>
<ScrollView
ref='swiper_ScrollView'
horizontal={true}
showsHorizontalScrollIndicator={false}
{...this._panResponder.panHandlers}
scrollEnabled={false}
>
{
pageArr.map((item,index)=>{
return (
<View style={[styles.pageItem,{width:screent_width}]} key={index}>
<Image style={styles.pageItemImg} source={item}></Image>
</View>
)
})
}
</ScrollView>
<View style={styles.pagination}>
{
pageArr.map((item,index)=>{
return (
<TouchableHighlight
underlayColor='#fff'
onPress={this.ScrollView_move.bind(this,false,index)}
key={index} style={[styles.paginationItem,{backgroundColor:index==swiperIndex?"red":"#fff"}]}>
<Text></Text>
</TouchableHighlight>
)
})
}
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1
}
});
ViewPagerAndroid滑动翻页和使用setPage点击翻页
一个允许在子视图之间左右翻页的容器。每一个 ViewPagerAndroid
的子容器会被视作一个单独的页,并且会被拉伸填满 ViewPagerAndroid
。
注:所有的子视图都必须是纯 View
,而不能是自定义的复合容器,ViewPagerAndroid必须设置大小,不然子视图内容不显示。
安装:
yarn add @react-native-community/viewpager
react-native link @react-native-community/viewpager//react-native的版本小于0.60执行,否则跳过这步
常用属性和方法:initialPage
:初始选中的页的下标,类型是number
onPageSelected
:在页面切换完成后(当用户在页面间滑动)调用,其中event.nativeEvent.position
是当前页的下标setPage
:用于ViewPager
滚动到指定页面
使用:
import React, {Component} from 'react';
import {Image, StyleSheet, Text, View,TouchableHighlight} from 'react-native';
import ViewPager from "@react-native-community/viewpager";
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
pageArr:[require('./src/images/1.jpg'),require('./src/images/2.jpg'),require('./src/images/3.jpg'),require('./src/images/4.jpg'),require('./src/images/5.jpg')],
swiperIndex:0
}
}
render() {
const {pageArr,swiperIndex}=this.state;
return (
<View style={styles.container}>
<View style={styles.swiperContainer}>
<ViewPager style={styles.ViewPager} initialPage={swiperIndex}
ref='ViewPager'
onPageSelected={(event)=>{
this.setState({
swiperIndex:event.nativeEvent.position
})
}}
>
{
pageArr.map((item,index)=>{
return (
<View style={styles.pageItem} key={index}>
<Image style={styles.pageItemImg} source={item}></Image>
</View>
)
})
}
</ViewPager>
<View style={styles.pagination}>
{
pageArr.map((item,index)=>{
return (
<TouchableHighlight
underlayColor='transparent'
onPress={()=>{
this.refs.ViewPager.setPage(index);//点击滚动到指定页
this.setState({
swiperIndex:index
})
}}
key={index} style={[styles.paginationItem,{backgroundColor:index==swiperIndex?"red":"#fff"}]}>
<Text></Text>
</TouchableHighlight>
)
})
}
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1
}
});
swiper_style.js
文件的代码如下所示:
import React from 'react';
import {
StyleSheet
} from 'react-native';
const swiper_styles = StyleSheet.create({
swiperContainer:{
width:'100%',
height:200,
position:'relative',
},
ViewPager:{
width:'100%',
height:'100%',
},
pageItem:{
width:'100%',
height:'100%',
},
pageItemImg:{
width:'100%',
height:'100%'
},
pagination:{
position:"absolute",
bottom:10,
zIndex:2,
height:12,
width:'100%',
justifyContent:"center",
flexDirection:"row",
alignItems:"center",
},
paginationItem:{
width:10,
height:10,
borderRadius:50,
marginRight:10
}
});
module.exports = swiper_styles;
运行结果:
这只是简单的翻页功能,有时间的话我会在写其他的,比如自动翻页、循环翻页等,至于啥时候写或者写完我也不知道,此处省略。。。。