在我们开发Android的时候,ViewPage这个控件的使用频率还是很高的,最简单的就是制作引导页,应用程序的主界面等,在ReactNative开发中实现该功能的组件是ViewPageAndroid,当你看到该组件是以Android结尾,你就明白该组件只对Android平台有效,如果使用就要考虑适配iOS(目前学习到的ScrollView组件可以实现此效果,具体实现不在本篇文章介绍),今天就通过下面示例图,介绍ViewPageAndroid的API以及使用。
基本用法
对于该组件内部可以嵌套View,每一个子View就相当于一个Page,每一个单独的页面显示时它会拉伸填满ViewPageAndroid。
return (
<ViewPagerAndroid style={{backgroundColor: 'red', flex: 1}}>
<View ><Text>1</Text></View>
<View><Text>2</Text></View>
<View><Text>3 </Text></View>
</ViewPagerAndroid>
)
在上面我么给出了一个最简单的展示ViewPagerAndroid的例子。我们在其内部加入了3个View,那么也将显示3页,虽然View没有设置样式,如宽和高,,但是它会填充ViewPagerAndroid ,其实设置了宽和高也没有用,不管设置宽高多少都是填满ViewPageAndroid。如果不信你可以尝试给第一个View添加样式
style={{backgroundColor:'green'}}
设置后,发现第一页显示的背景是绿色。然后再给第一个View增加宽高属性,都设置为100.如下
style={{backgroundColor:'green',width:100,height:100}}
设置后发现第一页的背景仍然全部是绿色,设置宽高属性并没有产生什么作用。对于文章开始的示例图展示,我们就是在VewPageAndroid组件中添加了5个子View,每一个View中有一个Image用于显示图片,和一个可点击的组件并且显示点击次数。
const styles = StyleSheet.create({
button: {
backgroundColor: '#2196f3',
borderRadius: 5,
marginHorizontal: 20,
marginTop: 10,
padding: 10,
},
buttonText: {
color: 'white',
},
container: {
flex: 1,
backgroundColor: 'white',
},
image: {
width: 300,
height: 200,
padding: 20,
},
viewPager: {
flex: 1,
},
});
由于ViewPageAndroid 5页显示的内容只是图片,背景不一样,其他都是通用的,我们就按如下创建
render() {
var pages = []
for (var i = 0; i < PAGES; i++) {
var pageStyle = {
backgroundColor: BGCOLOR[i % BGCOLOR.length],
alignItems: 'center',
padding: 20,
}
pages.push(
<View key={i} style={pageStyle} collapsable={false}>
<Image
style={styles.image}
resizeMode={Image.resizeMode.contain}
source={IMAGE_URIS[i % BGCOLOR.length]}
/>
<CustomCount/>
</View>
)
}
return (
<View style={styles.container}>
<ViewPagerAndroid
style={styles.viewPager}
ref={(viewPage) => {
this.viewPage = viewPage;
}}>
{pages}
</ViewPagerAndroid>
</View>
)
}
用到的图片资源常量以及背景常量和页数常量如下
const PAGES = 5;
const BGCOLOR = ['#fdc08e', '#fff6b9', '#99d1b7', '#dde5fe', '#f79273'];
const IMAGE_URIS = [
require('./Thumbnails/cat.png'),
require('./Thumbnails/monkey.png'),
require('./Thumbnails/rabbit.png'),
require('./Thumbnails/tiger.png'),
require('./Thumbnails/duck.png'),
];
对于Image组件通过source指定要显示的图片,其它属性使用可以参考之前的文章ReactNative Image组件详解,CustomCount是定义的一个组件,
class CustomCount extends Component {
state = {
count: 1,
}
render() {
return (
<View>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => this.setState({count: this.state.count + 1})}
style={{backgroundColor: '#38adff', borderRadius: 5, marginTop: 20, padding: 10}}
>
<Text>我是可点击的 {this.state.count}</Text>
</TouchableOpacity>
</View>)
}
}
在定义的点击组件中设置一个状态count,用于显示点击次数。这样我们就可以实现看到大致效果了。
设置初始化时显示页数
在默认的时候,总是显示第一页,很多时候,我们需要显示指定的页数,例如我们实现了一个日历,有12页(12个月),那我们点击打开日历时,要显示当前月的信息。如果当前是8月,那么就要默认显示第八页,不需要再我们一页一页的翻到该页,这时候就要使用initialPage 属性,它可以指定第一个显示的页数,该值从0开始。如设置默认显示第二页,如下
initialPage={1}
keyboardDismissMode
如果我们使用了用于输入的组件,就会弹出软键盘,那么在拖动翻页时需要隐藏软键盘,就需要使用此属性,它有两个值分别是none(默认值,拖拽不会让键盘消失)和on-drag(当拖拽开始的时候会让键盘消失)。如果我们设置滑动时隐藏软键盘,如下
keyboardDismissMode="on-drag"
设置每相邻页之间的间距
在上面的展示图中,我们看到每两个相邻页显示有10像素的白色间距,这个效果是通过pageMargin属性设置的,颜色对于间距显示的的颜色,是ViewPagerAndroid中样式设置的背景色,如果没有设置,从它父视图继承。如我们设置间距10像素
pageMargin={10}
scrollEnabled
该属性是用来设置是否可以滚动支持,当设置true时表示可以滚动翻页,默认值也是true,如果设置false的话,就表示不可滚动翻页,如此此时想实现翻页效果,那就需要使用setPage方法,稍后再介绍其使用。
显示页数指示器
在图例中,我们看到有一个显示当前页数以及总页数的指示器,要实现此功能,我们我们需要用到onPageSelected属性函数,每当页面切换完成后,该函数会调用,该函数有一个参数event,可以通过event.nativeEvent.position 获取当前页面的下标。
//增加属性
onPageSelected={this._onPageSelected}
_onPageSelected = (event) => {
console.log('_onPageSelected')
this.setState({page: event.nativeEvent.position});
}
我们增加了一个状态值page用于标示当前页面的下标。然后在ViewPageAndroid下面添加组件Text,用于显示当前页面指示器。
<Text style={[style, {textAlign: 'center'}]}>{this.state.page + 1}/{pages.length}</Text>
由于页面下标从0开始,我们显示时对其加1。通过上面我们实现了页面指示器显示。
很多时候,我们需要在需要在翻页时实现一些动画,例如翻页时Tab的颜色变化动画,在RN中,我们也可以实现效果,实现此效果时通过onPageScroll属性函数,当我们拖动页面时这个函数会一直回调,该函数有一个参数,我们可以通过event.nativeEvent获取我们需要的数据。
- position 从左数起第一个当前可见的页面的下标。(经过测试这个数据的用处不大,切记这个position和onPageSelected携带的position值不一样,不是当前页面下标)
- offset 一个在[0,1)(大于等于0,小于1)之间的范围,代表当前页面切换的状态。值x表示现在"position"所表示的页有(1 - x)的部分可见,而下一页有x的部分可见。
看到了把offset 变化时0到1之间的数值,当向左滑动翻页时(相当于下一页)该值时0到1变化,向右滑动翻页(相当于上一页)是1到0变化。我们就可以通过该值进行一些类似微信那种透明读,或者颜色深浅,等我们任何想要实现的动画。
onPageScrollStateChanged
该函数用于监测ViewPageAndroid的状态,它有三个值
- idle 空闲,意味着当前没有交互。
- dragging 拖动中,意味着当前页面正在被拖动。
- settling 处理中,意味着当前页面发生过交互,且正在结束开头或收尾的动画。
我们增加一个状态scrollState。然后如图例一样,将状态显示。
onPageScrollStateChanged={this._onPageScrollStateChanged}
_onPageScrollStateChanged = (state: ViewPagerScrollState) => {
console.log('_onPageScrollStateChanged')
this.setState({scrollState: state});
};
使用按钮实现上下翻页
在图例中我们有上一页和下一页两个按钮。实现此功能可以通过ViewPagerAndroid的setPage方法
_onPress = (offset) => {
var goPage = (this.state.page + offset + PAGES) % PAGES
if (this.state.animationsAreEnabled) {
this.viewPage.setPage(goPage)
} else {
this.viewPage.setPageWithoutAnimation(goPage)
}
this.setState({page: goPage})
}
我将上一页和下一页点击事件统一处理了,当点击下一页时参数传1,当点击上一页时参数传-1。goPage 即使我们对将要跳转的页面下标做计算。如果当前是第一页,再点击上一页时将跳转到最后一页,计算到要跳转的页面下标后,调用setPage或者setPageWithoutAnimation都可以实现,区别通过名字页显而易见。当使用setPage时最后一页和第一页相互切换时会有个过度动画。如果使用setPageWithoutAnimation就没有动画。
好了,ViewPageAndroid的相关介绍就到此为止了,想查看全部源码,可前往GitHub,今天的这篇文章就到此结束了,若文中有错误的地方欢迎指出,共同进步,谢谢。Have a wonderful day.