forked from vczero/react-native-lesson
-
Notifications
You must be signed in to change notification settings - Fork 0
/
第4篇react-native布局实战(二).html
417 lines (376 loc) · 11.2 KB
/
第4篇react-native布局实战(二).html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<style>
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote {
margin: 0;
padding: 0;
}
body {
font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
line-height: 18px;
color: #737373;
background-color: white;
margin: 10px 13px 10px 13px;
}
table {
margin: 10px 0 15px 0;
border-collapse: collapse;
}
td,th {
border: 1px solid #ddd;
padding: 3px 10px;
}
th {
padding: 5px 10px;
}
a {
color: #0069d6;
}
a:hover {
color: #0050a3;
text-decoration: none;
}
a img {
border: none;
}
p {
margin-bottom: 9px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: #404040;
line-height: 36px;
}
h1 {
margin-bottom: 18px;
font-size: 30px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 13px;
}
hr {
margin: 0 0 19px;
border: 0;
border-bottom: 1px solid #ccc;
}
blockquote {
padding: 13px 13px 21px 15px;
margin-bottom: 18px;
font-family:georgia,serif;
font-style: italic;
}
blockquote:before {
content:"\201C";
font-size:40px;
margin-left:-10px;
font-family:georgia,serif;
color:#eee;
}
blockquote p {
font-size: 14px;
font-weight: 300;
line-height: 18px;
margin-bottom: 0;
font-style: italic;
}
code, pre {
font-family: Monaco, Andale Mono, Courier New, monospace;
}
code {
background-color: #fee9cc;
color: rgba(0, 0, 0, 0.75);
padding: 1px 3px;
font-size: 12px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
pre {
display: block;
padding: 14px;
margin: 0 0 18px;
line-height: 16px;
font-size: 11px;
border: 1px solid #d9d9d9;
white-space: pre-wrap;
word-wrap: break-word;
}
pre code {
background-color: #fff;
color:#737373;
font-size: 11px;
padding: 0;
}
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
* {
-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
body {
width: 854px;
margin:10px auto;
}
}
@media print {
body,code,pre code,h1,h2,h3,h4,h5,h6 {
color: black;
}
table, pre {
page-break-inside: avoid;
}
}
</style>
<title>React-Native入门指南</title>
</head>
<body>
<h1>React-Native入门指南</h1>
<h2>第四篇React-Native布局实战(二)</h2>
<pre><code>在不断深入的过程中,发现React-Native布局和样式的坑还有很多,他没有像浏览器那样灵活和有规律可循,其中的规律需要我自己踩坑的时候发现。比如:不存在zIndex,后面的元素覆盖前面的元素;内层元素覆盖外层元素等等,borderRadius的设置,需要考虑到内层元素的位置等等。
</code></pre>
<h3>一、实战的内容</h3>
<pre><code>这里选用携程的App首页作为栗子,随不是严格的9宫格(比9宫格稍微难点...),但是可以很好的让我们练习flexbox.最后需要完成的结果如下:
</code></pre>
<p><img src="pic/4_0_1.png" alt="'首页'" /></p>
<h3>二、分解内容</h3>
<pre><code>整个页面我们可以分为几个部分,大致如下:
</code></pre>
<ul>
<li>头部</li>
<li>图片轮播</li>
<li>9宫格</li>
<li>底部活动</li>
</ul>
<h3>三、头部导航栏</h3>
<pre><code>因为,组件还没有讲,这里只是做一个简单的介绍。在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模块。
</code></pre>
<p><img src="pic/4_0_3.png" alt="'Index'" />
效果如下图:
<img src="pic/4_0_2.png" alt="'头部'" /></p>
<h3>四、图片轮播</h3>
<pre><code>这里图片轮播使用的是第三方组件react-native-swiper,当然React-Native是支持transform可以直接实现一套。我们启动npm命令行,在项目的根目录使用如下命令安装模块。
$ npm install react-native-swiper --save
$ npm i react-timer-mixin --save
</code></pre>
<p>(2)需要关闭React packager命令行和模拟器,在xcode中重启项目</p>
<pre><code>安装完成后,我们需要完成轮播功能。因为可以到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/>
</code></pre>
<h3>五、完成第一个9宫格布局,后面复制拷贝</h3>
<pre><code>其实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>
</code></pre>
<h3>六、样式类</h3>
<pre><code>说完了布局的原理,这里需要贴上样式仅供参考:
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提示错误信息的样式表中也没有提及,文档中也没有提及。所以后续还有不少的坑需要大家去一起探索。
</code></pre>
<h3>七、Index.js整个代码,仅供参考</h3>
<pre><code>实例代码中会涉及ScrollView组件,主要是为了适应小屏的机器,可以滚动视图。
</code></pre>
<p><a href="https://github.com/vczero/react-native-lession/tree/master/code/%E7%AC%AC4%E7%AF%87%E5%B8%83%E5%B1%80%E5%AE%9E%E6%88%98%EF%BC%88%E4%BA%8C%EF%BC%89%E4%BB%A3%E7%A0%81">代码链接:github</a></p>
</body>
</html>