一直以来,我们都在用原始的CSS属性来设置外边距、内边距和颜色。但是,最新的CSS规范中增加了弹性盒子的概念,非常利于我们对App的UI进行布局,虽然你可能还不太熟悉它。
React Native 使用了 css-layout 库,在这个库中实现了弹性盒子,而这种模型无论对iOS还是Android来说都很好理解。
更幸运的是,Facebook针对许多语言单独实现了这个项目,这就引申出了许多新颖的用法,比如[在SVG中应用弹性盒子布局](http://blog.scottlogic.com/2015/02/02/svg-layout-flexbox.html)(是的,这篇文章也是我写的,为此我不得不熬到深夜)。
在这个App中,采用了默认的垂直流式布局,即容器中的子元素按照从上到下的顺序进行布局。比如:
![](https://box.kancloud.cn/2015-10-27_562f20d280987.png)
这被称作主轴, 主轴可能是水平方向,也可能是垂直方向。
每个子元素的纵向位置由它们的边距(margin)、间距(padding)和高决定。容器的alignItems属性会被设置为居中(center),这决定了子元素在交叉轴上的位置。在本例里,将导致子元素水平居中对齐。
接下来我们添加一些文本输入框和按钮。打开SearchPage.js 在第二个 Text 元素后添加:
~~~
<View style={styles.flowRight}>
<TextInput
style={styles.searchInput}
placeholder='Search via name or postcode'/>
<TouchableHighlight style={styles.button}
underlayColor='#99d9f4'>
<Text style={styles.buttonText}>Go</Text>
</TouchableHighlight>
</View>
<TouchableHighlight style={styles.button}
underlayColor='#99d9f4'>
<Text style={styles.buttonText}>Location</Text>
</TouchableHighlight>
~~~
这段代码添加了两个顶级的视图:一个文本输入框外加一个按钮,以及一个单独的按钮。它们所使用的样式待会我们再介绍。
接着,在styles中增加如下样式:
~~~
flowRight: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch'
},
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
},
button: {
height: 36,
flex: 1,
flexDirection: 'row',
backgroundColor: '#48BBEC',
borderColor: '#48BBEC',
borderWidth: 1,
borderRadius: 8,
marginBottom: 10,
alignSelf: 'stretch',
justifyContent: 'center'
},
searchInput: {
height: 36,
padding: 4,
marginRight: 5,
flex: 4,
fontSize: 18,
borderWidth: 1,
borderColor: '#48BBEC',
borderRadius: 8,
color: '#48BBEC'
}
~~~
不同样式属性间以逗号分隔,这样你在container选择器后必须以一个逗号结尾。
这些样式将被文本输入框和按钮所用。
回到模拟器,按下Cmd+R ,你将看到如下效果:
![](https://box.kancloud.cn/2015-10-27_562f20d291be0.png)
Go按钮和其紧随的文本框在同一行,因此我们将它们用一个容器装在一起,同时容器的flexDirection: 样式属性设置为’row’ 。我们没有显式指定文本框和按钮的宽度,而是分别指定它们的flex样式属性为4和1。也就是说,它们的宽度在整个宽度(屏幕宽度)中所占的份额分别为4和1。
而且,视图中的两个按钮都不是真正的按钮。对于UIKit,按钮不过是可以点击的标签而已,因此React Native开发团队能够用JavaScript以一种简单的方式构建按钮:TouchableHighlight是一种React Native组件,当它被点击时,它的前景会变得透明,从而显示其隐藏在底部的背景色。
最后我们还要在视图中添加一张图片。这些图片可以在[此处](http://cdn2.raywenderlich.com/wp-content/uploads/2015/03/ReactNative-HouseImage.zip)下载。下载后解压缩zip文件。
在 Xcode 打开 Images.xcassets 文件,点击加号按钮,添加一个新的image set。然后将需要用到的图片拖到image set右边窗口对应的位置。
![](https://box.kancloud.cn/2015-10-27_562f20d2a9c92.png)
要让这些图片显示,必须停止你的 React Native App并重新启动。
在location按钮对应的 TouchableHighlight 组件下加入:
`<Image source={require('image!house')} style={styles.image}/>`
然后,为图片添加适当的样式定义,记得在上一个样式之后添加一个逗号结尾:
~~~
image: {
width: 217,
height: 138
}
~~~
由于我们将图片添加到了Images.xcasset资源包中,我们需要用require(‘image!house’)语句获得图片在App包中的正确路径。在Xcode中,打开Images.xcassets ,你可以找到名为house的image set。
回到模拟器,按下Cmd+R 查看运行效果:
![](https://box.kancloud.cn/2015-10-27_562f20d2d09c0.png)
> 注意: 如果图片没有显示,却看到一个““image!house” cannot be
> found”的提示,则可以重启packager(在终端中输入npm start命令)。
到目前为止,我们的App看上去有模有样,但它还缺少很多实际的功能。接下来的任务就是为App增加一些状态,执行一些动作。