之前我们讲了很多react-native的基础控件,为了方便大家的理解,我们来对react-native的布局做一个总结,观看本节知识,你将看到。
我们知道在Android中是用设备像素来作为单位的(后面又出现了百分比这么 一个概念),ios中后面也有了Auto Layout和1倍图,二倍图等概念(xib+storyboard)。然而react的宽度不支持百分比,那么React怎么提供尺寸的呢?PixelRatio,PixelRatio及像素密度,可以看看官方的介绍。
var image = getImage({
width: 200 * PixelRatio.get(),
height: 100 * PixelRatio.get()
});
<Image source={image} style={{width: 200, height: 100}} />
我们知道一个div如果不设置宽度,默认的会占用100%的宽度, 为了验证100%这个问题, 做三个实验:
<Text style={[styles.text, styles.header]}>
根节点上放一个元素,不设置宽度
</Text>
<View style={{height: 20, backgroundColor: '#333333'}} />
<Text style={[styles.text, styles.header]}>
固定宽度的元素上放一个View,不设置宽度
</Text>
<View style={{width: 100}}>
<View style={{height: 20, backgroundColor: '#333333'}} />
</View>
<Text style={[styles.text, styles.header]}>
flex的元素上放一个View,不设置宽度
</Text>
<View style={{flexDirection: 'row'}}>
<View style={{flex: 1}}>
<View style={{height: 20, backgroundColor: '#333333'}} />
</View>
<View style={{flex: 1}}/>
</View>
来看一下运行的结果:
css 里边经常会将一个文本或者图片水平垂直居中,如果使用过css 的flexbox当然知道使用alignItems 和 justifyContent ,那如果用React Native如何实现呢?
<Text style={[styles.text, styles.header]}>
水平居中
</Text>
<View style={{height: 100, backgroundColor: '#333333', alignItems: 'center'}}>
<View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
</View>
<Text style={[styles.text, styles.header]}>
垂直居中
</Text>
<View style={{height: 100, backgroundColor: '#333333', justifyContent: 'center'}}>
<View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
</View>
<Text style={[styles.text, styles.header]}>
水平垂直居中
</Text>
<View style={{height: 100, backgroundColor: '#333333', alignItems: 'center', justifyContent: 'center'}}>
<View style={{backgroundColor: '#fefefe', width: 30, height: 30, borderRadius: 15}}/>
</View>
通常页面不是很复杂的时候,我们可以使用flex布局等分做到网格,复杂的那么就要用ListView实现,或者第三方控件。
<View style={styles.flexContainer}>
<View style={styles.cell}>
<Text style={styles.welcome}>
cell1
</Text>
</View>
<View style={styles.cell}>
<Text style={styles.welcome}>
cell2
</Text>
</View>
<View style={styles.cell}>
<Text style={styles.welcome}>
cell3
</Text>
</View>
</View>
styles = {
flexContainer: {
// 容器需要添加direction才能变成让子元素flex
flexDirection: 'row'
},
cell: {
flex: 1,
height: 50,
backgroundColor: '#aaaaaa'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
},
}
另一种方式可以参照我之前的实现: React Native实现九宫格效果
<Text style={styles.welcome}> 100px height </Text>
<Image style={{height: 100}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
100px 高度, 可以看到图片适应100高度和全屏宽度,背景居中适应未拉伸但是被截断也就是cover。
<Text style={styles.welcome}> 100px height with resizeMode contain </Text>
<View style={[{flex: 1, backgroundColor: '#fe0000'}]}>
<Image style={{flex: 1, height: 100, resizeMode: Image.resizeMode.contain}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
</View>
contain 模式容器完全容纳图片,图片自适应宽高。
<Text style={styles.welcome}> 100px height with resizeMode cover </Text>
<View style={[{flex: 1, backgroundColor: '#fe0000'}]}>
<Image style={{flex: 1, height: 100, resizeMode: Image.resizeMode.cover}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
</View>
stretch模式图片被拉伸适应屏幕
<Text style={styles.welcome}> set height to image container </Text>
<View style={[{flex: 1, backgroundColor: '#fe0000', height: 100}]}>
<Image style={{flex: 1}} source={{uri: 'http://gtms03.alicdn.com/tps/i3/TB1Kcs5GXXXXXbMXVXXutsrNFXX-608-370.png'}} />
</View>
<View style={{flex: 1, height: 100, backgroundColor: '#333333'}}>
<View style={[styles.circle, {position: 'absolute', top: 50, left: 180}]}>
</View>
</View>
styles = {
circle: {
backgroundColor: '#fe0000',
borderRadius: 10,
width: 20,
height: 20
}
}
和css的标准不同的是, 元素容器不用设置position:’absolute|relative’ 。
<View style={{flex: 1, height: 100, backgroundColor: '#333333'}}>
<View style={[styles.circle, {position: 'relative', top: 50, left: 50, marginLeft: 50}]}>
</View>
</View>
我们知道在css中区分inline元素和block元素,既然react-native实现了一个超级小的css subset。那我们就来实验一下padding和margin在inline和非inline元素上的padding和margin的使用情况。
padding
<Text style={[styles.text, styles.header]}>
在正常的View上设置padding
</Text>
<View style={{padding: 30, backgroundColor: '#333333'}}>
<Text style={[styles.text, {color: '#fefefe'}]}> Text Element</Text>
</View>
<Text style={[styles.text, styles.header]}>
在文本元素上设置padding
</Text>
<View style={{padding: 0, backgroundColor: '#333333'}}>
<Text style={[styles.text, {backgroundColor: '#fe0000', padding: 30}]}>
text 元素上设置paddinga
</Text>
</View>
margin
<Text style={[styles.text, styles.header]}>
在正常的View上设置margin
</Text>
<View style={{backgroundColor: '#333333'}}>
<View style={{backgroundColor: '#fefefe', width: 30, height: 30, margin: 30}}/>
</View>
<Text style={[styles.text, styles.header]}>
在文本元素上设置margin
</Text>
<View style={{backgroundColor: '#333333'}}>
<Text style={[styles.text, {backgroundColor: '#fe0000', margin: 30}]}>
text 元素上设置margin
</Text>
<Text style={[styles.text, {backgroundColor: '#fe0000', margin: 30}]}>
text 元素上设置margin
</Text>
</View>
先看看文字有哪些支持的style属性:
Attributes.style = {
color string
containerBackgroundColor string
fontFamily string
fontSize number
fontStyle enum('normal', 'italic')
fontWeight enum("normal", 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900')
lineHeight number
textAlign enum("auto", 'left', 'right', 'center')
writingDirection enum("auto", 'ltr', 'rtl')
}
实际上React-native里边是没有样式继承这种说法的, 但是对于Text元素里边的Text元素是可以继承的。到底是继承的最外层的Text的值呢,还是继承父亲Text的值呢?肯定是继承父亲Text的值。
<Text style={[styles.text, styles.header]}>
文本样式继承
</Text>
<View style={{backgroundColor: '#333333', padding: 10}}>
<Text style={{color: 'white'}}>
<Text style={{color: 'red'}} onPress={this.onPressTitle}>
文本元素{'\n'}
<Text>我是white还是red呢?{'\n'} </Text>
</Text>
<Text>我应该是white的</Text>
</Text>
</View>
针对上面的实例,我们做一个总结。