鍍金池/ 教程/ HTML/ React-Native入門指南
React-Native入門指南
React-Native入門指南
React-Native入門指南
React-Native入門指南
React-Native入門指南
React-Native入門指南
React-Native入門指南

React-Native入門指南

第四篇React-Native布局實(shí)戰(zhàn)(二)

在不斷深入的過程中,發(fā)現(xiàn)React-Native布局和樣式的坑還有很多,他沒有像瀏覽器那樣靈活和有規(guī)律可循,其中的規(guī)律需要我自己踩坑的時(shí)候發(fā)現(xiàn)。比如:不存在zIndex,后面的元素覆蓋前面的元素;內(nèi)層元素覆蓋外層元素等等,borderRadius的設(shè)置,需要考慮到內(nèi)層元素的位置等等。

一、實(shí)戰(zhàn)的內(nèi)容

這里選用攜程的App首頁作為栗子,隨不是嚴(yán)格的9宮格(比9宮格稍微難點(diǎn)...),但是可以很好的讓我們練習(xí)flexbox.最后需要完成的結(jié)果如下:

http://wiki.jikexueyuan.com/project/react-native-lesson/images/4_0_1.png" alt="'首頁'" />

二、分解內(nèi)容

整個(gè)頁面我們可以分為幾個(gè)部分,大致如下:
  • 頭部
  • 圖片輪播
  • 9宮格
  • 底部活動(dòng)

三、頭部導(dǎo)航欄

因?yàn)?,組件還沒有講,這里只是做一個(gè)簡單的介紹。在React-Native中實(shí)現(xiàn)頭部導(dǎo)航欄很簡單,只要使用NavigatorIOS組件即可?,F(xiàn)在開工。

1、我們?cè)趇ndex.ios.js中添加如下代碼;同時(shí)創(chuàng)建文件夾pagaes和pages下創(chuàng)建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:引入外部模塊,就像,引入我們自己創(chuàng)建的/pages/Index.js一樣。
 (2)引入定義NavigatorIOS、AppRegistry、StyleSheet組件和類。
 (3)在render中調(diào)用NavigatorIOS組件,initialRoute是初始化路由,title是當(dāng)前頁面的頭部標(biāo)題;component是當(dāng)前路由下顯示的組件;
 (4)注意:這里NavigatorIOS的style需要設(shè)置大小,比如這里設(shè)置是flex:1,否則就不能顯示內(nèi)容主體;
 (5)最后我們需要注冊(cè)當(dāng)前應(yīng)用:AppRegistry.registerComponent('HelloWorld', () => NV);

 2、創(chuàng)建Index.js文件,文件的內(nèi)容如下, module.exports就暴露了Index模塊。

http://wiki.jikexueyuan.com/project/react-native-lesson/images/4_0_3.png" alt="'Index'" /> 效果如下圖: http://wiki.jikexueyuan.com/project/react-native-lesson/images/4_0_2.png" alt="'頭部'" />

四、圖片輪播

這里圖片輪播使用的是第三方組件react-native-swiper,當(dāng)然React-Native是支持transform可以直接實(shí)現(xiàn)一套。我們啟動(dòng)npm命令行,在項(xiàng)目的根目錄使用如下命令安裝模塊。

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

(2)需要關(guān)閉React packager命令行和模擬器,在xcode中重啟項(xiàng)目

安裝完成后,我們需要完成輪播功能。因?yàn)榭梢缘絞ithub看看swiper暴露的接口和參數(shù)。github地址是:https://github.com/leecade/react-native-swiper

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

(2)使用swiper,將輪播圖封裝成單獨(dú)的組件
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的時(shí)候直接用:<Slider/>

五、完成第一個(gè)9宮格布局,后面復(fù)制拷貝

其實(shí)4個(gè)九宮格都是一樣,這個(gè)其實(shí)可以封裝成組件,這里采用拷貝的形式,開發(fā)一個(gè),其他3個(gè)就ok的,不會(huì)偷懶的工程師,不是好工程師[偷笑]。分析下布局:
(1)其實(shí)首先是3個(gè)列在一行的布局,那么外層組件是需要flexDirection: 'row',各占據(jù)寬度的1/3,即各自flex:1;
(2)每個(gè)列內(nèi)又分兩行, 需要每個(gè)行都是flex:1,各占據(jù)高度的一半;
(3)第一列是文字圖片組合,其余都是文字組合;
(4)所有行內(nèi)元素都是水平、垂直居中;
(5)這里使用了個(gè)TouchableHighlight組件,是為了出發(fā)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]}>團(tuán)購.特惠</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中圖片的大小是不會(huì)根據(jù)給定一個(gè)寬度或者高度而自適應(yīng)大小的,因此我們需要讓圖片根據(jù)寬度或者高度來自適應(yīng),那么可以使用resizeMode:Image.resizeMode.contain。facebook提示錯(cuò)誤信息的樣式表中也沒有提及,文檔中也沒有提及。所以后續(xù)還有不少的坑需要大家去一起探索。

七、Index.js整個(gè)代碼,僅供參考

實(shí)例代碼中會(huì)涉及ScrollView組件,主要是為了適應(yīng)小屏的機(jī)器,可以滾動(dòng)視圖。

代碼鏈接:github