RN布局實踐:開發京東客戶端首頁(一)


1.京東客戶端首頁布局分析

如圖所示,京東客戶端首頁布局基本分為以下幾個部分:

(1)頭部:搜索欄,由京東logo、搜索輸入框和掃描按鈕組成

(2)內容部分:父級元素為ListView或ScrollView,可滑動,其中包括一個輪播圖、一組功能按鈕和秒殺、拍賣商品列表

(3)底部:TabBar,用於切換頁面

 

2.創建工程和相關文件、目錄

首先,我們利用react-native init命令創建一個名為JdApp(當然也可以自己起)的React Native工程(具體操作請參考: http://blog.csdn.net/yuanguozhengjust/article/details/50468050),項目結構如下圖所示:
根據我們剛才對京東客戶端結構的分析,目前可以先新建幾個文件,用於拆分代碼,具體方案如下:
images目錄:用於存放相關圖片
Header.js:用於構建頭部搜索欄(本文主要介紹此文件中的內容)
MainScreen.js:主屏幕文件,起到最外層控制作用
HomePage.js:首頁文件,用於構建輪播圖、功能按鈕、特價列表等
 

3.調研相關控件

目前App中需要用到輪播圖、Tab這兩個高級控件,而React Native原生的控件僅有TabBarIOS可供iOS平台使用,不能滿足我們的需求,根據在Github上搜索的結果,我們可以選用以下幾個第三方控件進行開發:
react-native-viewpager:可實現輪播圖效果,地址: https://github.com/race604/react-native-viewpager
react-native-tab-navigator:可用於構建Tab,並可以輕松地進行頁面切換,地址: https://github.com/exponentjs/react-native-tab-navigator
有興趣的讀者,還可以自行構建Tab和Swiper這種控件,做一個符合項目需求的控件並不難,但想要擴展性、通用性更強,不是一件容易的事情。
 

4.分析搜索欄的基本布局

頭部的搜索欄,分為三個部分:logo、輸入框、掃碼按鈕。
其中,logo可以使用Image控件
輸入框稍復雜,外層是一個圓角的View,其內部左側是一個Image,用於展示放大鏡Icon,中間為一個TextInput控件用於輸入,右側為一個Image,用於展示語音搜索Icon
右側掃碼按鈕也比較簡單,僅為一個Image
那么根據FlexBox布局原則,可以按以下方式進行布局:
這里特別說明一下,由於React Native不支持自動計算Image等View的大小(參見: http://facebook.github.io/react-native/docs/images.html#why-not-automatically-size-everything),所以我們不能像Android的XML那樣,設置為wrap_content,必須為Image指定寬度和高度,而由於React Native使用的是類似Android dp的像素,所以請根據設計圖的尺寸自行計算,這里推薦一個網站: https://pixplicity.com/dp-px-converter/
 

5.代碼實現

確定好了搜索欄的布局,那么我們就開始具體使用JavaScript代碼進行實現,首先新建一個Header.js的文件,並引入我們需要用到的控件
1 'use strict'; 
3 import React, {
4     Component
5     Image,
6     TextInput
7     View,
8     StyleSheet
9 } from 'react-native';

接着聲明類和樣式,之所以使用export,是因為要在其他類中使用(如:MainScreen)

1 export default class Header extends Component {
3 } 
5 const styles = StyleSheet.create({   
7 });

然后在Header類的render()方法中編寫JSX代碼,在StyleSheet.create()方法中,編寫類CSS的樣式,如下:

 1 export default class Header extends Component {
 2     render() {
 3         return (
 4             <View style={styles.container}>
 5  
 6             </View>
 7         )
 8     }
 9 }
10  
11 const styles = StyleSheet.create({
12     container: {
13         flexDirection: 'row',
14         paddingLeft: 10,
15         paddingRight: 10,
16         paddingTop: Platform.OS === 'ios' ? 20 : 0,   // 處理iOS狀態欄
17         height: Platform.OS === 'ios' ? 68 : 48,   // 處理iOS狀態欄
18         backgroundColor: '#d74047',
19         alignItems: 'center'
20     }});

然后我們在模擬器或者真機上跑一下,看看效果

嗯,不錯,貌似是我們想要的效果!接着把圖片資源導入項目中去,很簡單,只需要在目錄創建文件夾,將圖片復制進去,WebStorm等IDE即可自動識別
根據我們之前的分析,完成樣式表的設計,如下:
 1 const styles = StyleSheet.create({
 2     container: {
 3         flexDirection: 'row',   // 水平排布
 4         paddingLeft: 10,
 5         paddingRight: 10,
 6         paddingTop: Platform.OS === 'ios' ? 20 : 0,  // 處理iOS狀態欄
 7         height: Platform.OS === 'ios' ? 68 : 48,   // 處理iOS狀態欄
 8         backgroundColor: '#d74047',
 9         alignItems: 'center'  // 使元素垂直居中排布, 當flexDirection為column時, 為水平居中
10     },
11     logo: {
12         height: 24,
13         width: 64,
14         resizeMode: 'stretch'  // 設置拉伸模式
15     },
16     searchBox: {
17         height: 30,
18         flexDirection: 'row',
19         flex: 1,  // 類似於android中的layout_weight,設置為1即自動拉伸填充
20         borderRadius: 5,  // 設置圓角邊
21         backgroundColor: 'white',
22         alignItems: 'center',
23         marginLeft: 8,
24         marginRight: 12
25     },
26     scanIcon: {
27         height: 26.7,
28         width: 26.7,
29         resizeMode: 'stretch'
30     },
31     searchIcon: {
32         marginLeft: 6,
33         marginRight: 6,
34         width: 16.7,
35         height: 16.7,
36         resizeMode: 'stretch'
37     },
38     voiceIcon: {
39         marginLeft: 5,
40         marginRight: 8,
41         width: 15,
42         height: 20,
43         resizeMode: 'stretch'
44     },
45     inputText: {
46         flex: 1,
47         backgroundColor: 'transparent',
48         fontSize: 14
49     }
50 });

請認真注意上面代碼中的注釋,標有注釋的地方,即為和普通iOS、Android開發不太一樣的地方!
由於我們已經將父級元素的排布方向改為水平,所以我們只需將需要展現的元素放入<View>的子元素即可,如下代碼所示:

 1 export default class Header extends Component {
 2     render() {
 3         return (
 4             <View style={styles.container}>
 5                 <Image source={require('./images/header/header_logo.png')} style={styles.logo}/>
 6                 <View style={styles.searchBox}>
 7                     <Image source={require('./images/header/icon_search.png')} style={styles.searchIcon}/>
 8                     <TextInput
 9                         keyboardType='web-search'
10                         placeholder='搜索京東商品/店鋪'
11                         style={styles.inputText}/>
12                     <Image source={require('./images/header/icon_voice.png')} style={styles.voiceIcon}/>
13                 </View>
14                 <Image source={require('./images/header/icon_qr.png')} style={styles.scanIcon}/>
15             </View>
16         )
17     }
18 }
需要注意的是:
1.style的使用,當使用StyleSheet創建的樣式時,外層只需要一層{},而直接聲明需要再加一層,即直接聲明了匿名變量
2.Image的source可以使用網絡圖片或本地資源,使用本地資源時,類似require.js的包引用,而使用網絡資源時,使用方法如下:source={{uri:'http://xxxxxxx'}}
3.TextInput的鍵盤類型可以使用keyboardType進行設置,占位字符使用placeholder設置,具體請參見官方文檔
 
這時在模擬器或真機上Reload JS一下,就可以看到我們想要的界面了:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM