React-Native入门指南

第四篇React-Native布局实战(二)

  1. 在不断深入的过程中,发现React-Native布局和样式的坑还有很多,他没有像浏览器那样灵活和有规律可循,其中的规律需要我自己踩坑的时候发现。比如:不存在zIndex,后面的元素覆盖前面的元素;内层元素覆盖外层元素等等,borderRadius的设置,需要考虑到内层元素的位置等等。

一、实战的内容

  1. 这里选用携程的App首页作为栗子,随不是严格的9宫格(比9宫格稍微难点...),但是可以很好的让我们练习flexbox.最后需要完成的结果如下:

'首页'

二、分解内容

  1. 整个页面我们可以分为几个部分,大致如下:
  • 头部
  • 图片轮播
  • 9宫格
  • 底部活动

三、头部导航栏

  1. 因为,组件还没有讲,这里只是做一个简单的介绍。在React-Native中实现头部导航栏很简单,只要使用NavigatorIOS组件即可。现在开工。
  2. 1、我们在index.ios.js中添加如下代码;同时创建文件夹pagaespages下创建Index.js
  3. var React = require('react-native');
  4. var Index = require('./pages/Index');
  5. var {
  6. NavigatorIOS,
  7. AppRegistry,
  8. StyleSheet,
  9. } = React;
  10. var NV = React.createClass({
  11. render: function(){
  12. return(
  13. <NavigatorIOS
  14. style={styles.container}
  15. initialRoute={{
  16. title: '首页',
  17. component: Index,
  18. }}
  19. />
  20. );
  21. }
  22. });
  23. var styles = StyleSheet.create({
  24. container: {
  25. flex: 1,
  26. }
  27. });
  28. AppRegistry.registerComponent('HelloWorld', () => NV);
  29. 分析代码:
  30. 1require:引入外部模块,就像,引入我们自己创建的/pages/Index.js一样。
  31. 2)引入定义NavigatorIOSAppRegistryStyleSheet组件和类。
  32. 3)在render中调用NavigatorIOS组件,initialRoute是初始化路由,title是当前页面的头部标题;component是当前路由下显示的组件;
  33. 4)注意:这里NavigatorIOSstyle需要设置大小,比如这里设置是flex1,否则就不能显示内容主体;
  34. 5)最后我们需要注册当前应用:AppRegistry.registerComponent('HelloWorld', () => NV);
  35. 2、创建Index.js文件,文件的内容如下, module.exports就暴露了Index模块。

'Index'
效果如下图:
'头部'

四、图片轮播

  1. 这里图片轮播使用的是第三方组件react-native-swiper,当然React-Native是支持transform可以直接实现一套。我们启动npm命令行,在项目的根目录使用如下命令安装模块。
  2. $ npm install react-native-swiper --save
  3. $ npm install react-timer-mixin --save

(2)需要关闭React packager命令行和模拟器,在xcode中重启项目

  1. 安装完成后,我们需要完成轮播功能。因为可以到github看看swiper暴露的接口和参数。github地址是:https://github.com/leecade/react-native-swiper
  2. 1)引入swiper,前面也提到了require.
  3. var Swiper = require('react-native-swiper');
  4. 2)使用swiper,将轮播图封装成单独的组件
  5. var sliderImgs = [
  6. 'http://images3.c-ctrip.com/SBU/apph5/201505/16/app_home_ad16_640_128.png',
  7. 'http://images3.c-ctrip.com/rk/apph5/C1/201505/app_home_ad49_640_128.png',
  8. 'http://images3.c-ctrip.com/rk/apph5/D1/201506/app_home_ad05_640_128.jpg'
  9. ];
  10. var Slider = React.createClass({
  11. render: function(){
  12. return (
  13. <Swiper style={styles.wrapper} showsButtons={false} autoplay={true} height={150} showsPagination={false}>
  14. <Image style={[styles.slide,]} source={{uri: sliderImgs[0]}}></Image>
  15. <Image style={[styles.slide,]} source={{uri: sliderImgs[1]}}></Image>
  16. <Image style={[styles.slide,]} source={{uri: sliderImgs[2]}}></Image>
  17. </Swiper>
  18. );
  19. }
  20. });
  21. (3)这样我们可以直接在render的时候直接用:<Slider/>

五、完成第一个9宫格布局,后面复制拷贝

  1. 其实4个九宫格都是一样,这个其实可以封装成组件,这里采用拷贝的形式,开发一个,其他3个就ok的,不会偷懒的工程师,不是好工程师[偷笑]。分析下布局:
  2. 1)其实首先是3个列在一行的布局,那么外层组件是需要flexDirection: 'row',各占据宽度的1/3,即各自flex:1
  3. 2)每个列内又分两行, 需要每个行都是flex:1,各占据高度的一半;
  4. 3)第一列是文字图片组合,其余都是文字组合;
  5. 4)所有行内元素都是水平、垂直居中;
  6. 5)这里使用了个TouchableHighlight组件,是为了出发onPress事件,类似于click或者touch事件。
  7. <View style={[styles.sbu_red, styles.sbu_view]}>
  8. <TouchableHighlight underlayColor={'#FA6778'} style={{flex:1}}>
  9. <View style={[styles.sbu_flex, styles.sbu_borderRight]}>
  10. <View style={[styles.sub_con_flex, styles.sub_text]}>
  11. <Text style={[styles.font16]}>酒店</Text>
  12. </View>
  13. <View style={[styles.sub_con_flex]}>
  14. <Image style={[styles.sbu_icon_img]} source={{uri:BUIcon[0]}}></Image>
  15. </View>
  16. </View>
  17. </TouchableHighlight>
  18. <View style={[styles.sbu_flex, styles.sbu_borderRight]}>
  19. <View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}>
  20. <Text style={[styles.font16]}>海外</Text>
  21. </View>
  22. <View style={[styles.sub_con_flex, styles.sub_text]}>
  23. <Text style={[styles.font16]}>周边</Text>
  24. </View>
  25. </View>
  26. <View style={[styles.sbu_flex]}>
  27. <View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}>
  28. <Text style={[styles.font16]}>团购.特惠</Text>
  29. </View>
  30. <View style={[styles.sub_con_flex, styles.sub_text]}>
  31. <Text style={[styles.font16]}>客栈.公寓</Text>
  32. </View>
  33. </View>
  34. </View>

六、样式类

  1. 说完了布局的原理,这里需要贴上样式仅供参考:
  2. var styles = StyleSheet.create({
  3. //container
  4. container:{
  5. backgroundColor:'#F2F2F2',
  6. flex:1,
  7. },
  8. //slider
  9. wrapper: {
  10. height:80,
  11. },
  12. slide: {
  13. height:80,
  14. resizeMode: Image.resizeMode.contain,
  15. },
  16. //sbu
  17. sbu_view:{
  18. height:84,
  19. marginLeft: 5,
  20. marginRight:5,
  21. borderWidth:1,
  22. borderRadius:5,
  23. marginBottom:10,
  24. flexDirection:'row',
  25. },
  26. sbu_red:{
  27. backgroundColor: '#FA6778',
  28. borderColor:'#FA6778',
  29. marginTop:-70,
  30. },
  31. sbu_blue:{
  32. backgroundColor: '#3D98FF',
  33. borderColor:'#3D98FF',
  34. },
  35. sbu_green:{
  36. backgroundColor: '#5EBE00',
  37. borderColor:'#5EBE00',
  38. },
  39. sbu_yellow:{
  40. backgroundColor: '#FC9720',
  41. borderColor:'#FC9720',
  42. },
  43. sbu_flex:{
  44. flex:1,
  45. },
  46. sbu_borderRight:{
  47. borderColor:'#fff',
  48. borderRightWidth: 0.5,
  49. },
  50. sbu_icon_img:{
  51. height:40,
  52. width:40,
  53. resizeMode:Image.resizeMode.contain,
  54. },
  55. sub_con_flex:{
  56. flex:1,
  57. justifyContent: 'center',
  58. alignItems: 'center',
  59. },
  60. sub_text:{
  61. justifyContent:'center',
  62. },
  63. font16:{
  64. fontSize:17,
  65. color:'#FFF',
  66. fontWeight:'900',
  67. },
  68. sbu_borderBottom:{
  69. borderBottomWidth:0.5,
  70. borderBottomColor:'#fff',
  71. },
  72. img_view:{
  73. height:62,
  74. marginLeft:5,
  75. marginRight:5,
  76. flexDirection: 'row',
  77. marginBottom:20,
  78. backgroundColor:'#fff',
  79. },
  80. img_flex:{
  81. flex:1,
  82. borderWidth:1,
  83. borderColor:'#ccc',
  84. },
  85. img_wh: {
  86. height:59,
  87. borderRightWidth:0,
  88. resizeMode:Image.resizeMode.contain,
  89. }
  90. });
  91. 着重说下resizeMode:Image.resizeMode.contain。在React-Native中图片的大小是不会根据给定一个宽度或者高度而自适应大小的,因此我们需要让图片根据宽度或者高度来自适应,那么可以使用resizeMode:Image.resizeMode.containfacebook提示错误信息的样式表中也没有提及,文档中也没有提及。所以后续还有不少的坑需要大家去一起探索。

七、Index.js整个代码,仅供参考

  1. 实例代码中会涉及ScrollView组件,主要是为了适应小屏的机器,可以滚动视图。

代码链接:github