ViewPager是Android中比较常见的页面切换控件, 同时, 在UIExplorerApp中也有ViewPagerAndroid的示例. 通过使用这个控件, 理解ReactNative的实现逻辑. 我们现在来分析一下ViewPager的使用方式和ReactNative的编程要点, 本文注释也很清晰.

效果

1. 准备

新建ReactNative的项目.

npm install -g react-native-clireact-native init [TestViewPager]

-g是全局, react-native-cli是react-native的命令行工具(command line interface). 安装需要管理员权限(sudo), 安装一次即可, 使用react-native命令. 参考.

修改项目架构, 主页直接跳转至ViewPager模块.

'use strict';var React = require('react-native');var {  AppRegistry,} = React;var ViewPagerModule = require('./ViewPagerModule/index')AppRegistry.registerComponent('TestViewPager', () => ViewPagerModule);

2. 概述

ViewPager包含若干滑动页面; 点赞选项-模拟页面交互; 按键和滚动条-模拟滚动监听.

'use strict'var React = require('react-native');var {  View,  Text,  Image,  TouchableNativeFeedback, // 触碰响应  TouchableOpacity, // 触碰更换透明度的属性  ViewPagerAndroid, // Android的ViewPager} = React;// Stylesvar styles = require('./style');var PAGES = 5; // 页数// 颜色var BGCOLOR = ['#8ad3da', '#eecde2', '#e682b4', '#b7badd','#f1c7dd'];// 本地图片地址var IMAGE_URIS = [  require('./images/jessicajung.png'),  require('./images/tiffany.png'),  require('./images/seohyun.png'),  require('./images/taeyeon.png'),  require('./images/yoona.png'),];// 名称var NAMES = ['Jessica', 'Tiffany', 'Seohyun', 'Taeyeon', 'Yoona'];/** * 点赞功能页面 * @param {likes: 点赞数} * @return {点赞视图} [点赞按钮, 动态增加点赞数] */var LikeCount = React.createClass({  // 初始化状态  getInitialState: function() {    return {      likes: 0,    };  },  // 点击增加  onClick: function() {    this.setState({likes: this.state.likes + 1});  },  render: function() {    var thumbsUp = '\uD83D\uDC4D'; // 图标    return (      <View style = {styles.likeContainer}>        <TouchableOpacity          onPress={this.onClick}          style={styles.likeButton}>          <Text style={styles.likesText}>            {thumbsUp}          </Text>        </TouchableOpacity>        <Text style={styles.likesText}>          {this.state.likes + ' 喜欢'}        </Text>      </View>    );  },});/** * 按钮: 添加点击状态(enabled)和文本(text) * @param {enabled:点击状态} {text:显示文本} {onPress:点击事件} * @return {TouchableNativeFeedback} [触摸反馈的视图] */var Button = React.createClass({  _handlePress: function() {    if (this.props.enabled && this.props.onPress) {      this.props.onPress();    }  },  render: function() {    return (      <TouchableNativeFeedback onPress={this._handlePress}>        <View style={[styles.button, this.props.enabled ? {} : styles.buttonDisabled]}>          <Text style={styles.buttonText}>            {this.props.text}          </Text>        </View>      </TouchableNativeFeedback>    );  }});/** * 滚动条, fractionalPosition滚动条长度, progressBarSize当前大小 * @param {size:滚动条大小} {progress:过程} * @return {View} [里外两层视图, 背景白框黑底, 显示白框] */var ProgressBar  = React.createClass({  render: function() {    var fractionalPosition = (this.props.progress.position + this.props.progress.offset);    var progressBarSize = (fractionalPosition / (PAGES - 1)) * this.props.size;    return (      <View style={[styles.progressBarContainer, {width: this.props.size}]}>        <View style={[styles.progressBar, {width: progressBarSize}]}/>      </View>    );  }});var ViewPagerModule = React.createClass({  /** * 初始化状态 * @return {状态} [页面] */  getInitialState: function() {    return {      page: 0, // 当前位置      progress: { // Progress位置        position: 0,        offset: 0,      }    };  },  // 页面选择  onPageSelected: function(e) {    this.setState({page: e.nativeEvent.position});  },  // 页面滚动  onPageScroll: function(e) {    this.setState({progress: e.nativeEvent});  },  // 移动页面  move: function(delta) {    var page = this.state.page + delta;    this.go(page);  },  // 跳转页面  go: function(page) {    this.viewPage.setPage(page);    this.setState({page});  },  render: function() {    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={'cover'}            source={IMAGE_URIS[i%PAGES]}            />          <Text style={styles.nameText}>            {NAMES[i%PAGES]}          </Text>          <LikeCount />        </View>      );    }    var {page} = this.state;    return (      <View style={styles.container}>        <ViewPagerAndroid          style={styles.viewPager}          initialPage={0}          onPageScroll={this.onPageScroll}          onPageSelected={this.onPageSelected}          ref={viewPager => {this.viewPage = viewPager;}}>          {pages}        </ViewPagerAndroid>        <View style={styles.buttons}>          <Button            text="首页"            enabled={page > 0}            onPress={() => this.go(0)}/>          <Button            text="上一页"            enabled={page > 0}            onPress={() => this.move(-1)}/>          <Text style={styles.buttonText}>            页 {page+1} / {PAGES}          </Text>          {/*进度条*/}          <ProgressBar            size={80}            progress={this.state.progress}/>          <Button            text="下一页"            enabled={page < PAGES - 1}            onPress={() => this.move(1)}/>          <Button            text="尾页"            enabled={page < PAGES - 1}            onPress={() => this.go(PAGES -1)}/>        </View>      </View>    );  },});module.exports = ViewPagerModule;

引入RN的原生模块

var {  View,  Text,  Image,  TouchableNativeFeedback, // 触碰响应  TouchableOpacity, // 触碰更换透明度的属性  ViewPagerAndroid, // Android的ViewPager} = React;

TouchableNativeFeedback, 接触时会受到原生的响应; TouchableWithoutFeedback, 接触时无响应. TouchableOpacity, 接触时会改变透明度. 在加入onclick方法时, 可以模拟按钮视图.

定义控件: LikeCount点赞, Button按钮, ProgressBar滚动条.

3. 点赞(LikeCount)控件

likes存储喜欢的数量. 点击时, 更新数量状态, 刷新页面. 其中, 喜欢按钮是触碰控件, 在接触时会改变透明度(Opacity).

/** * 点赞功能页面 * @param {likes: 点赞数} * @return {点赞视图} [点赞按钮, 动态增加点赞数] */var LikeCount = React.createClass({  // 初始化状态  getInitialState: function() {    return {      likes: 0,    };  },  // 点击增加  onClick: function() {    this.setState({likes: this.state.likes + 1});  },  render: function() {    var thumbsUp = '\uD83D\uDC4D'; // 图标    return (      <View style = {styles.likeContainer}>        <TouchableOpacity          onPress={this.onClick}          style={styles.likeButton}>          <Text style={styles.likesText}>            {thumbsUp}          </Text>        </TouchableOpacity>        <Text style={styles.likesText}>          {this.state.likes + ' 喜欢'}        </Text>      </View>    );  },});

直接调用, 即可使用.

<LikeCount />

state的like属性, 仅仅作用于当前页面, 每次更新时刷新.
注意: 一定要谨慎使用全局state, 这样会刷新整个页面, 影响效率.

4. 按钮(Button)控件

添加使用状态, 是否可以点击, 根据状态修改视图样式和点击回调.

/** * 按钮: 添加点击状态(enabled)和文本(text) * @param {enabled:点击状态} {text:显示文本} {onPress:点击事件} * @return {TouchableNativeFeedback} [触摸反馈的视图] */var Button = React.createClass({  _handlePress: function() {    if (this.props.enabled && this.props.onPress) {      this.props.onPress();    }  },  render: function() {    return (      <TouchableNativeFeedback onPress={this._handlePress}>        <View style={[styles.button, this.props.enabled ? {} : styles.buttonDisabled]}>          <Text style={styles.buttonText}>            {this.props.text}          </Text>        </View>      </TouchableNativeFeedback>    );  }});

在RN中, 并没有提供Button视图, 可以使用Touchable类的视图, 设置点击事件, 如TouchableNativeFeedback, 根据状态, 修改按钮的样式和点击. 注意: props表示属性, 在使用视图时提供.

使用Button, 设置text显示, enabled状态, onPress点击事件.

          <Button            text="首页"            enabled={page > 0}            onPress={() => this.go(0)}/>

5. 滚动条(ProgressBar)控件

主要监听ViewPager的滚动事件, 这和Android的滚动非常类似, fractionalPosition是偏移比例, progressBarSize是偏移量.

/** * 滚动条, fractionalPosition滚动条长度, progressBarSize当前大小 * @param {size:滚动条大小} {progress:过程} * @return {View} [里外两层视图, 背景白框黑底, 显示白框] */var ProgressBar  = React.createClass({  render: function() {    var fractionalPosition = (this.props.progress.position + this.props.progress.offset);    var progressBarSize = (fractionalPosition / (PAGES - 1)) * this.props.size;    return (      <View style={[styles.progressBarContainer, {width: this.props.size}]}>        <View style={[styles.progressBar, {width: progressBarSize}]}/>      </View>    );  }});

控件需要设置ProgressBar的属性progress(滚动位置)和size(大小).

使用控件, 属性: size大小; progress进度状态, 其中position是位置, offset是偏移.

      progress: { // Progress位置        position: 0,        offset: 0,      }      ...          <ProgressBar            size={80}            progress={this.state.progress}/>

注意: progress是主页面属性, 重置状态时, 刷新全部页面.

6. ViewPager页面

根据页面定制属性, 根据页面ID设置不同图片和文字.

 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={'cover'} source={IMAGE_URIS[i%PAGES]} /> <Text style={styles.nameText}> {NAMES[i%PAGES]} </Text> <LikeCount /> </View> ); }

注意设置图片资源时,
使用IMAGE_URIS =['xxx.png']require(IMAGE_URIS[i%PAGES])会显示模块丢失.
在数组IMAGE_URIS使用require('./images/jessicajung.png')加载source就可以.
思考很久的问题…

ViewPager页面

 <View style={styles.container}> <ViewPagerAndroid  style={styles.viewPager} initialPage={0} onPageScroll={this.onPageScroll} onPageSelected={this.onPageSelected} ref={viewPager => {this.viewPage = viewPager;}}> {pages} </ViewPagerAndroid> <View style={styles.buttons}> <Button  text="首页" enabled={page > 0} onPress={() => this.go(0)}/> <Button  text="上一页" enabled={page > 0} onPress={() => this.move(-1)}/> <Text style={styles.buttonText}> 页 {page+1} / {PAGES} </Text> {/*进度条*/} <ProgressBar  size={80} progress={this.state.progress}/> <Button  text="下一页" enabled={page < PAGES - 1} onPress={() => this.move(1)}/> <Button  text="尾页" enabled={page < PAGES - 1} onPress={() => this.go(PAGES -1)}/> </View> </View>

使用方法, 监听ViewPagerAndroid的事件, onPageScroll页面滚动, onPageSelected页面选择, 按钮关联页面. 核心在于go方法, 设置stateviewPage页.

  // 跳转页面  go: function(page) {    this.viewPage.setPage(page);    this.setState({page});  },

7. Styles

引入styles, 使用独立文件.

// Stylesvar styles = require('./style');

样式

'use strict';var React = require('react-native');var {  StyleSheet,} = React;var styles = StyleSheet.create({  buttons: {    flexDirection: 'row',    height: 40,    backgroundColor: 'pink',    alignItems: 'center',    justifyContent: 'space-between',  },  // 按钮可点击状态  button: {    flex: 1,    width: 0,    margin: 2,    borderColor: 'gray',    borderWidth: 1,    backgroundColor: 'gray',  },  // 按钮非点击装  buttonDisabled: {    backgroundColor: 'black',    opacity: 0.5,  },  buttonText: {    fontSize: 12,    color: 'white',    textAlign: 'center',  },  // 文字显示  nameText: {    fontSize: 16,    margin: 4,    color: 'white',    textAlign: 'center',  },  container: {    flex: 1,    backgroundColor: 'white',  },  image: {    flex: 1,    width: 300,    padding: 20,  },  likeButton: {    backgroundColor: 'rgba(0, 0, 0, 0.1)',    borderColor: '#333333',    borderWidth: 1,    borderRadius: 5,    flex: 1,    margin: 8,    padding: 8,  },  likeContainer: {    flexDirection: 'row',  },  likesText: {    flex: 1,    fontSize: 18,    alignSelf: 'center',  },  progressBarContainer: {    height: 10,    margin: 5,    borderColor: '#eeeeee',    borderWidth: 2,  },  progressBar: {    alignSelf: 'flex-start',    flex: 1,    backgroundColor: '#eeeeee',  },  viewPager: {    flex: 1,  },});module.exports = styles;

里面包含各个控件的样式, 主要使用了Flex+RN的Style.

动画效果

Github下载地址

OK, 通过实现简单的ViewPagerAndroid学习了很多知识.

更多相关文章

  1. Android(安卓)开发笔记4-- 常用控件
  2. Android(安卓)Chronometer控件使用,计时器
  3. Android(安卓)M 新控件 TabLayout 与 NavigationView 实践
  4. Android布局和intent实例
  5. Android处理touch冲突的解决办法
  6. Android学习笔记十四之RelativeLayout相对布局
  7. Android(安卓)自定义控件实现ListView索引
  8. (笔记)Android(安卓)studio——相对布局(RelativeLayout)
  9. 【Android(安卓)Studio】制作启动画面Splash Screen

随机推荐

  1. android ViewPager学习笔记1
  2. android添加监听器
  3. Android(安卓)混淆打包
  4. Android WIFI,蓝牙,电池,背光,SD卡,摄像头,按键
  5. Android adb.exe程序启动不起来
  6. android Activity间List传值
  7. Android 消息通知栏Notification使用和权
  8. Android Property实现介绍
  9. 如何获得Android的System Bar’s Height
  10. Could not find gradle wrapper within A