开始学习React Native,首先必须了解其布局的特性,因为其与传统的Web开发中的布局有着不小的差异。
React Native#Dimensions
RN提供的
API可以让我们在应用程序内获得屏幕和窗体的宽高尺寸。
- Dimensions
- var { height, width } = Dimensions.get("window");
- var { height: height2, width: width2 } = Dimensions.get("screen");
- return (
- <View style={styles.container}>
- <Text style={styles.welcome}>Welcome to React Native!</Text>
- <Text style={styles.instructions}>
- {`The window width is ${width}, height is ${height}`}
- </Text>
- <Text style={styles.instructions}>
- {`The screen width is ${width2}, height is ${height2}`}
- </Text>
- </View>
- );
在Nexus 5X(420DPI, 1080x1920)模拟器效果如下:
窗体与屏幕尺寸之间的差异主要是,窗体仅仅指可以布局的区域,而屏幕指整个设备尺寸范围,那么垂直方向的设备,两者之间在高度上的差异就主要是虚拟按键和状态栏高度。
1080物理像素宽度实际显示的宽度约411,这个411的单位实际上是RN中特殊的尺寸单位
,全称
- dp
,即密度无关像素。这个概念有点类似于Web浏览器中的
- Density-independent Pixel
。
- ViewPoint
认定在一个160DPI的设备上
- DP
=
- 1dp
,所以Nexus 5X的宽度可以如下计算
- 1px
~=
- 1080*160/420
。
- 411
Density-independent Pixel
RN中各元素采用Flex布局,这与Web CSS3中的Flex布局整体接近,但在默认值,可用属性方面有一些区别:
现在使用默认的
,实现水平居中、垂直居中、水平垂直居中。
- flexDirection:column
- <View
- style={{
- flex: 1,
- justifyContent: "center",
- alignItems: "stretch"
- }}
- >
- <View
- style={{
- flex: 1,
- backgroundColor: "red",
- alignItems: "center"
- }}
- >
- <View
- style={{
- width: 50,
- height: 50,
- backgroundColor: "#eaeaea"
- }}
- >
- <Text style={{ color: "#222" }}>水平居中</Text>
- </View>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "yellow",
- justifyContent: "center"
- }}
- >
- <View
- style={{
- width: 50,
- height: 50,
- backgroundColor: "#eaeaea"
- }}
- >
- <Text style={{ color: "#222" }}>垂直居中</Text>
- </View>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "blue",
- justifyContent: "center",
- alignItems: "center"
- }}
- >
- <View
- style={{
- width: 50,
- height: 50,
- backgroundColor: "#eaeaea"
- }}
- >
- <Text style={{ color: "#222" }}>水平垂直居中</Text>
- </View>
- </View>
- </View>
再来实现一个等分的网格布局:
- <View
- style={{
- flex: 1,
- flexDirection: "row",
- alignItems: "flex-start"
- }}
- >
- <View
- style={{
- flex: 1,
- backgroundColor: "red",
- height: 30
- }}
- >
- <Text style={{ color: "white" }}>Cell 1</Text>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "yellow",
- height: 30
- }}
- >
- <Text style={{ color: "#000" }}>Cell 2</Text>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "blue",
- height: 30
- }}
- >
- <Text style={{ color: "white" }}>Cell 3</Text>
- </View>
- </View>
实现左边固定,右边固定,中间非固定的三栏布局:
- <View
- style={{
- flex: 1,
- flexDirection: "row",
- alignItems: "flex-start"
- }}
- >
- <View
- style={{
- width: 50,
- backgroundColor: "red",
- height: 30
- }}
- >
- <Text style={{ color: "white" }}>Cell 1</Text>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "yellow",
- height: 30
- }}
- >
- <Text style={{ color: "#000" }}>Cell 2</Text>
- </View>
- <View
- style={{
- width: 50,
- backgroundColor: "blue",
- height: 30
- }}
- >
- <Text style={{ color: "white" }}>Cell 3</Text>
- </View>
- </View>
大多数情况,只需要调节如下几个重要布局属性即可:
- enum flexDirection {
- row,
- column,
- "row-reverse",
- "column-reverse"
- }
- enum flexWrap {
- wrap,
- nowrap
- }
- enum justifyContent {
- "flex-start",
- "flex-end",
- "center",
- "space-between",
- "space-around"
- }
- enum alignItems {
- "flex-start",
- "flex-end",
- "center",
- "stretch"
- }
要记住的一点即是
定义的是子元素沿主轴方向(flexDirect为column时是垂直方向,为row时是水平方向)的排列,
- justifyContent
定义的是子元素沿侧轴方向(flexDirect为column时是水平方向,为row时是垂直方向)的排列。由于主轴方向是1-N个子元素排列,因此多了
- alignItems
和
- space-between
的属性值来决定布局,示例如下:
- space-around
- <View
- style={{
- flex: 1,
- flexDirection: "row",
- justifyContent: "center"
- }}
- >
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "space-between",
- alignItems: "center"
- }}
- >
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>between</Text>
- </View>
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>between</Text>
- </View>
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>between</Text>
- </View>
- </View>
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "space-around",
- alignItems: "center",
- backgroundColor: "#aaa"
- }}
- >
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>around</Text>
- </View>
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>around</Text>
- </View>
- <View
- style={{
- width: 50,
- backgroundColor: "#5ba4e5",
- height: 100
- }}
- >
- <Text style={{ color: "white" }}>around</Text>
- </View>
- </View>
- </View>
RN中绝对与相对定位仍然可以使用,但是父级容器元素无需定义
,子元素按直接父级进行定位。
- position
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "center"
- }}
- >
- <View
- style={{
- flex: 1,
- backgroundColor: "#eaeaea"
- }}
- >
- <View
- style={{
- width: 100,
- height: 100,
- backgroundColor: "#5ba4e5",
- position: "relative",
- left: 20,
- top: 50
- }}
- >
- <Text style={{ color: "white", flexWrap: "wrap" }}>
- relative left 20, top 50
- </Text>
- </View>
- </View>
- <View
- style={{
- flex: 1,
- backgroundColor: "#888"
- }}
- >
- <View
- style={{
- width: 100,
- height: 100,
- backgroundColor: "#5ba4e5",
- position: "absolute",
- left: 100,
- top: 60
- }}
- >
- <Text style={{ color: "white", flexWrap: "wrap" }}>
- absolute left 100, top 60
- </Text>
- </View>
- </View>
- </View>
分别对
和
- View
组件进行padding测试,两个分别对应
- Text
与
- block
元素。
- inline
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "center"
- }}
- >
- <View
- style={{
- backgroundColor: "#666",
- padding: 50
- }}
- >
- <Text
- style={{
- color: "white",
- flexWrap: "wrap",
- backgroundColor: "#234"
- }}
- >
- view padding 50
- </Text>
- </View>
- <View
- style={{
- backgroundColor: "#888"
- }}
- >
- <Text
- style={{
- padding: 50,
- color: "white",
- flexWrap: "wrap",
- backgroundColor: "#234"
- }}
- >
- text padding 50
- </Text>
- </View>
- <View style={{ flex: 1 }} />
- </View>
可以看到不论是Text(深蓝背景)还是View(灰色背景)均可撑开容器高度。
仍然按照上面例子,只是为有
属性的元素再添加一个固定高度200:
- padding
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "center"
- }}
- >
- <View
- style={{
- backgroundColor: "#666",
- padding: 50,
- height: 200
- }}
- >
- <Text
- style={{
- color: "white",
- flexWrap: "wrap",
- backgroundColor: "#234"
- }}
- >
- view padding 50 height 200
- </Text>
- </View>
- <View
- style={{
- backgroundColor: "#888",
- padding: 50
- }}
- >
- <Text
- style={{
- color: "white",
- flexWrap: "wrap",
- backgroundColor: "#234"
- }}
- >
- view padding 50
- </Text>
- </View>
- <View style={{ flex: 1 }} />
- </View>
可以看出
包含了
- height
在内。
- padding
如果
换成
- padding
:
- margin
- <View
- style={{
- flex: 1,
- flexDirection: "column",
- justifyContent: "center"
- }}
- >
- <View style={{ backgroundColor: "#eaeaea" }}>
- <View
- style={{
- backgroundColor: "#234",
- margin: 50,
- height: 200
- }}
- >
- <Text
- style={{
- color: "white",
- flexWrap: "wrap"
- }}
- >
- view margin 50 height 200
- </Text>
- </View>
- </View>
- <View style={{ backgroundColor: "#aaaaaa" }}>
- <View
- style={{
- backgroundColor: "#234",
- height: 200
- }}
- >
- <Text
- style={{
- color: "white",
- flexWrap: "wrap"
- }}
- >
- view margin 0 height 200
- </Text>
- </View>
- </View>
- <View style={{ flex: 1 }} />
- </View>
图片中的
(蓝色区域)高度均为200,而添加了
- View
之后,其实际高度未变,即height的计算是不包括
- margin
。
- margin
来源: http://www.tuicool.com/articles/fiQryi3