360SDN.COM

React-Native入门指南-第4篇React-Native布局实战

来源:  2017-05-31 17:17:04    评论:0点击:

来源:http://vczero.github.io/react_native/%E7%AC%AC4%E7%AF%87%E5%AD%A6%E4%BC%9Areact-native%E5%B8%83%E5%B1%80.html

前辈教导我们,掌握一门新技术的最快方法是练习。因此,我找了下比较有爱,暖气的界面。当然不是给美团打广告了,只是觉得页面蛮清新的。下面就是要显示的效果:

美团

第三篇文章基本上对React-Native的布局基本上有个大致的认识,现在开工吧。总体上,该页面分三个部分:(1)我们约会吧及其右边3栏;(2)1元吃大餐及其底下的4栏;(3)红火来袭的三栏。

一、实现第一部分

1、首先,我们创建一个项目
现在我们需要创建一个React-Native的项目,因此可以按照下面的步骤:
打开终端,开始React-Native开发的旅程吧。
(1)安装命令行工具(已经安装了就不用再安装了):sudo npm install -g react-native-cli
(2)创建一个空项目:react-native init HelloWorld
(3)找到创建的HelloWorld项目,双击HelloWorld.xcodeproj即可在xcode中打开项目。xcodeproj是xcode的项目文件。
(4)在xcode中,使用快捷键cmd + R即可启动项目。

2、清除其余多余的代码,剩下的代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';

var React = require('react-native');
var {
    AppRegistry,
    StyleSheet,
    Text,
    View,
} = React;


var HelloWorld = React.createClass({
    render: function() {
        return (
            <View></View>
        );
    }
});
var styles = StyleSheet.create({

});


AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

3、此时,除了闪屏外,看到应该是空白的页面。开工,分析页面:
(1)大致有4个板块
(2)先是左右两栏(1/3和2/3);后是上下两栏(1/2)。我们先用View组件布局。

美团

4、完成初步布局
看如下代码,应该很清楚了,View里面嵌入并列的两栏。

美团

实现效果如下:

美团

5、添加内部图片和文字
其实做这种布局,还是有很多的细节,粗糙的效果如下,这块代码暂时不贴了,最后一并贴出来:

美团

二、按照第一部分原理,完成整个页面

完成的效果如下:

美团

整个代码如下:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';

var React = require('react-native');
var {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Image,
} = React;


var HelloWorld = React.createClass({
    render: function() {
        return (
            <View style={{}}>
                <View style={[styles.height160, styles.row,]}>
                <View style={[styles.height160, styles.part_1_left,]}>
                <Text style={[styles.font14, styles.marTop18, styles.marLeft10, styles.green]}>我们约吧</Text>
                <Text style={[styles.font10, styles.marTop14, styles.marLeft10]}>恋爱家人好朋友</Text>
                <Image style={[styles.yue]} source={{uri: 'http://p0.meituan.net/mmc/fe4d2e89827aa829e12e2557ded363a112289.png'}}></Image>
            </View>
            <View style={[styles.height160, styles.part_1_right,]}>
            <View style={[styles.row, {flex:1}]}>
            <View style={{flex:1}}>
              <Text style={[styles.font14, {marginLeft:30}, styles.red]}>超低价值</Text>
              <Text style={[styles.font14, {fontSize:12, marginTop:14, marginLeft:30,color: 'black'}]}>十元惠生活</Text>
            </View>
            <View style={[{flex:1}, {marginTop:-13}]}>
              <Image style={[styles.hanbao]} source={{uri: 'http://p0.meituan.net/mmc/a06d0c5c0a972e784345b2d648b034ec9710.jpg'}}></Image>
            </View>
          </View>
          <View style={[{flex:1, flexDirection: 'row',borderTopWidth:0.5, borderColor:'#DDD8CE'}]}>
            <View style={{flex:1, borderRightWidth:1, borderColor:'#DDD8CE',}}>
                <Text style={{color:'#F742AB', marginLeft:5,fontWeight:'bold', fontSize:15, marginTop:8}}>聚餐宴请</Text>
                <Text style={{fontSize:12,marginTop:4, marginLeft:5}}>朋友家人常聚聚</Text>
                <Image style={{height:25,width:25, alignSelf: 'center'}} source={{uri: 'http://p1.meituan.net/mmc/08615b8ae15d03c44cc5eb9bda381cb212714.png'}}></Image>
            </View>
            <View style={{flex:1,}}>
                <Text style={[styles.font14,{color:'#FF8601', marginTop:8, marginLeft:5}]}>名店抢购</Text>
                <Text style={[{marginLeft:5, fontSize:12,marginTop:4,}]}>还有</Text>
                <Text style={[{marginLeft:5, fontSize:12,marginTop:4,}]}>12:06:12分</Text>
            </View>
          </View>
        </View>
    </View>
    <View>
      <View style={{borderBottomWidth:1,borderTopWidth:1, borderColor:'#DDD8CE', marginTop:40,height:65, flexDirection: 'row',paddingTop:10}}>
        <View style={[{flex:1}]}>
            <Text style={{fontSize:17, color:'#FF7F60', fontWeight:'900', marginLeft:7}}>一元吃大餐</Text>
            <Text style={{marginLeft:7, fontSize:12, marginTop:3}}>新用户专享</Text>
        </View>
        <View style={{flex:1}}>
            <Image style={{height:50, width:120}} source={{uri:'http://p1.meituan.net/280.0/groupop/7f8208b653aa51d2175848168c28aa0b23269.jpg'}}></Image>
        </View>
      </View>
    </View>
    <View>
      <View style={{flexDirection: 'row',}}>
        <View style={[styles.row, {borderColor:'#DDD8CE', borderRightWidth:1}]}>
          <View style={{flex:1,}}>
            <Text style={{fontSize:17, color:'#EA6644', fontWeight:'bold', marginLeft:7}}>撸串节狂欢</Text>
            <Text style={{fontSize:12, color:'#97979A', marginTop:3, marginLeft:7}}>烧烤6.6元起</Text>
          </View>
          <View style={{flex:1}}>
            <Image style={{width:60,height:55}} source={{uri: 'http://p1.meituan.net/280.0/groupop/fd8484743cbeb9c751a00e07573c3df319183.png'}}></Image>
          </View>
        </View>
        <View style={styles.row}>
          <View style={{flex:1}}>
            <Text style={{fontSize:17, color:'#EA6644', fontWeight:'bold', marginLeft:7}}>毕业旅行</Text>
            <Text style={{fontSize:12, color:'#97979A', marginTop:3, marginLeft:7}}>选好酒店才安心</Text>
          </View>
          <View style={{flex:1}}>
            <Image style={{width:60,height:55}} source={{uri: 'http://p0.meituan.net/280.0/groupop/ba4422451254f23e117dedb4c6c865fc10596.jpg'}}></Image>
          </View>
        </View>
      </View>
      <View style={{flexDirection: 'row',}}>
        <View style={[styles.row, {borderColor:'#DDD8CE', borderRightWidth:1,  marginLeft:1},]}>
          <View style={{flex:1}}>
            <Text style={{fontSize:17, color:'#EA6644', fontWeight:'bold', marginLeft:7}}>0元餐来袭</Text>
            <Text style={{fontSize:12, color:'#97979A', marginTop:3, marginLeft:7}}>免费吃喝玩乐购</Text>
          </View>
          <View style={{flex:1}}>
            <Image style={{width:60,height:55}} source={{uri: 'http://p0.meituan.net/280.0/groupop/6bf3e31d75559df76d50b2d18630a7c726908.png'}}></Image>
          </View>
        </View>
        <View style={styles.row}>
          <View style={{flex:1}}>
            <Text style={{fontSize:17, color:'#EA6644', fontWeight:'bold', marginLeft:7}}>热门团购</Text>
            <Text style={{fontSize:12, color:'#97979A', marginTop:3, marginLeft:7}}>大家都在买什么</Text>
          </View>
          <View style={{flex:1}}>
            <Image style={{width:60,height:55}} source={{uri: 'http://p1.meituan.net/mmc/a616a48152a895ddb34ca45bd97bbc9d13050.png'}}></Image>
          </View>
        </View>
      </View>
    </View>
  </View>
);

} });

var styles = StyleSheet.create({
    row:{
    flexDirection: 'row',
    paddingTop:20
},
marTop18:{
    marginTop:18,
},
marTop14:{
    marginTop:14,
},
font14:{
    fontSize:14,
},
font10:{
    fontSize:12,
},
height160:{
    height: 160
},
yue:{
    height:80,
},
green:{
    color:'#55A44B',
    fontWeight: '900'
},
red:{
    color: '#FF3F0D',
    fontWeight: '900'
},
marLeft10:{
    marginLeft:10,
},
part_1_left:{
    flex: 1,
    borderColor: '#DCD7CD',
    borderRightWidth: 0.5,
    borderBottomWidth: 1,
},
part_1_right:{
    flex:2,
    borderColor: '#DCD7CD',
    borderBottomWidth: 1,
},
hanbao:{
    height:55,
    width:55
}
});


AppRegistry.registerComponent('HelloWorld', () => HelloWorld);

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

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

一、实战的内容

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

'首页

二、分解内容

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

三、头部导航栏

因为,组件还没有讲,这里只是做一个简单的介绍。在React-Native中实现头部导航栏很简单,只要使用NavigatorIOS组件即可。现在开工。

1、我们在index.ios.js中添加如下代码;同时创建文件夹pagaes和pages下创建Index.js
var React = require('react-native');
var Index = require('./pages/Index');

var {
    NavigatorIOS,
    AppRegistry,
    StyleSheet,
} = React;

var NV = React.createClass({
    render: function(){
        return(
            <NavigatorIOS
                style={styles.container}
                initialRoute={{
                    title: '首页',
                    component: Index,
                }}
            />
        );
    }
});

var styles = StyleSheet.create({
    container: {
        flex: 1,
    }
});


AppRegistry.registerComponent('HelloWorld', () => NV);

分析代码:
 (1)require:引入外部模块,就像,引入我们自己创建的/pages/Index.js一样。
 (2)引入定义NavigatorIOS、AppRegistry、StyleSheet组件和类。
 (3)在render中调用NavigatorIOS组件,initialRoute是初始化路由,title是当前页面的头部标题;component是当前路由下显示的组件;
 (4)注意:这里NavigatorIOS的style需要设置大小,比如这里设置是flex:1,否则就不能显示内容主体;
 (5)最后我们需要注册当前应用:AppRegistry.registerComponent('HelloWorld', () => NV);

 2、创建Index.js文件,文件的内容如下, module.exports就暴露了Index模块。

'Index 效果如下图: '头部

四、图片轮播

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

$ npm install react-native-swiper --save
$ npm i react-timer-mixin --save

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

安装完成后,我们需要完成轮播功能。因为可以到github看看swiper暴露的接口和参数。github地址是:https://github.com/leecade/react-native-swiper

(1)引入swiper,前面也提到了require.
var Swiper = require('react-native-swiper');

(2)使用swiper,将轮播图封装成单独的组件
var sliderImgs = [
    'http://images3.c-ctrip.com/SBU/apph5/201505/16/app_home_ad16_640_128.png',
    'http://images3.c-ctrip.com/rk/apph5/C1/201505/app_home_ad49_640_128.png',
    'http://images3.c-ctrip.com/rk/apph5/D1/201506/app_home_ad05_640_128.jpg'
];
var Slider = React.createClass({
    render: function(){
    return (
      <Swiper style={styles.wrapper} showsButtons={false} autoplay={true} height={150} showsPagination={false}>
        <Image style={[styles.slide,]} source={{uri: sliderImgs[0]}}></Image>
        <Image style={[styles.slide,]} source={{uri: sliderImgs[1]}}></Image>
        <Image style={[styles.slide,]} source={{uri: sliderImgs[2]}}></Image>
      </Swiper>
    );
  }
});
(3)这样我们可以直接在render的时候直接用:<Slider/>

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

其实4个九宫格都是一样,这个其实可以封装成组件,这里采用拷贝的形式,开发一个,其他3个就ok的,不会偷懒的工程师,不是好工程师[偷笑]。分析下布局:
(1)其实首先是3个列在一行的布局,那么外层组件是需要flexDirection: 'row',各占据宽度的1/3,即各自flex:1;
(2)每个列内又分两行, 需要每个行都是flex:1,各占据高度的一半;
(3)第一列是文字图片组合,其余都是文字组合;
(4)所有行内元素都是水平、垂直居中;
(5)这里使用了个TouchableHighlight组件,是为了出发onPress事件,类似于click或者touch事件。

        <View style={[styles.sbu_red, styles.sbu_view]}>
        <TouchableHighlight underlayColor={'#FA6778'} style={{flex:1}}>
            <View style={[styles.sbu_flex, styles.sbu_borderRight]}>
                <View style={[styles.sub_con_flex, styles.sub_text]}>
                    <Text style={[styles.font16]}>酒店</Text>
                </View>
                <View style={[styles.sub_con_flex]}>
                    <Image style={[styles.sbu_icon_img]} source={{uri:BUIcon[0]}}></Image>
                </View>
            </View>
        </TouchableHighlight>
        <View style={[styles.sbu_flex, styles.sbu_borderRight]}>
            <View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}>
                <Text style={[styles.font16]}>海外</Text>
            </View>
            <View style={[styles.sub_con_flex, styles.sub_text]}>
                <Text style={[styles.font16]}>周边</Text>
            </View>
        </View>
        <View style={[styles.sbu_flex]}>
            <View style={[styles.sub_con_flex, styles.sub_text, styles.sbu_borderBottom]}>
                <Text style={[styles.font16]}>团购.特惠</Text>
            </View>
            <View style={[styles.sub_con_flex, styles.sub_text]}>
                <Text style={[styles.font16]}>客栈.公寓</Text>
            </View>
        </View>
    </View> 

六、样式类

说完了布局的原理,这里需要贴上样式仅供参考:
var styles = StyleSheet.create({
//container
container:{
    backgroundColor:'#F2F2F2',
    flex:1,
},
//slider
wrapper: {
    height:80,
},
slide: {
    height:80,
    resizeMode: Image.resizeMode.contain,
},
//sbu
sbu_view:{
    height:84,
    marginLeft: 5,
    marginRight:5,
    borderWidth:1,
    borderRadius:5,
    marginBottom:10,
    flexDirection:'row',
},
sbu_red:{
    backgroundColor: '#FA6778',
    borderColor:'#FA6778',
    marginTop:-70,
},

sbu_blue:{
    backgroundColor: '#3D98FF',
    borderColor:'#3D98FF',
},

sbu_green:{
    backgroundColor: '#5EBE00',
    borderColor:'#5EBE00',
},

sbu_yellow:{
    backgroundColor: '#FC9720',
    borderColor:'#FC9720',
},
sbu_flex:{
    flex:1,
},
sbu_borderRight:{
    borderColor:'#fff',
    borderRightWidth: 0.5,
},
sbu_icon_img:{
    height:40,
    width:40,
    resizeMode:Image.resizeMode.contain,
},
sub_con_flex:{
    flex:1,
    justifyContent: 'center',
    alignItems: 'center',
},
sub_text:{
    justifyContent:'center',
},
font16:{
    fontSize:17,
    color:'#FFF',
    fontWeight:'900',
},
sbu_borderBottom:{
    borderBottomWidth:0.5,
    borderBottomColor:'#fff',
},
img_view:{
    height:62,
    marginLeft:5,
    marginRight:5,
    flexDirection: 'row',
    marginBottom:20,
    backgroundColor:'#fff',
},
img_flex:{
    flex:1,
    borderWidth:1,
    borderColor:'#ccc',
},
img_wh: {
    height:59,
    borderRightWidth:0,
    resizeMode:Image.resizeMode.contain,
}
});

着重说下resizeMode:Image.resizeMode.contain。在React-Native中图片的大小是不会根据给定一个宽度或者高度而自适应大小的,因此我们需要让图片根据宽度或者高度来自适应,那么可以使用resizeMode:Image.resizeMode.contain。facebook提示错误信息的样式表中也没有提及,文档中也没有提及。所以后续还有不少的坑需要大家去一起探索。

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

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

代码链接:github

为您推荐

友情链接 |九搜汽车网 |手机ok生活信息网|ok生活信息网|ok微生活
 Powered by www.360SDN.COM   京ICP备11022651号-4 © 2012-2016 版权