RN中的布局我以为主要包含这几个部分:像素单位,布局方式,组件,CSS。熟悉这几点后,就是经验的积累,见得多了作的多了布局代码写起来天然就快许多。 html
react native 的页面布局使用的是flex布局,Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。flex只是一种元素布局方式,因此任何一个元素均可以设定flex,而一个元素设定了flex以后,那么它里面的全部元素都是在这个容器内布局。react
在RN中的flex布局跟web中略有不一样,RN中flex只能够指定一个数字, 根据具体数字值来填充展现当前元素,“1”即表示100%撑满当前容器,而该容器内的子元素只可以在该容器内区域布局。ios
2. 主次轴web
容器内默认有两根轴,横轴和纵轴,当画一个页面时,首先要肯定该页面或者该容器内是采用哪一个轴做为主轴布局,其实就是行布局或者列布局。当肯定主轴以后,另一轴自动成为副轴。RN中使用flexDirection来定义当前容器是使用何种布局(column活row),默认为column。justifyContent 和 alignItems 分别制定主轴和次轴的排列方式。ide
flexDirection: column;row;布局
justifyContent:flex
flex-start(默认,起始位置,通常都是左对齐);flexbox
center(居中);spa
flex-end(结尾,通常是右对齐);code
space-around;space-between;
alignItems:
flex-start(默认,起始位置,通常都是左对齐);
center(居中);
flex-end(结尾,通常是右对齐);
stretch(均匀分布);
当父容器指定了flex以后(好比1),那么若是子元素的flex也都设置为1,那么这些子元素将会平均分配父容器的尺寸来布局,就像以下代码:
<View style={{flex:1,flexDirection:'row',backgroundColor:'#ffffff'}}> <View style={{flex:1,backgroundColor:'red'}}></View> <View style={{flex:1,backgroundColor:'black'}}></View> <View style={{flex:1,backgroundColor:'blue'}}></View> </View>
![]() |
|
flexDirection:'column' | flexDirection:'row' |
再举个例子,子元素指定宽高,父容器采用space-between 和 space-around布局,代码以下:
<View style={{flex:1,borderWidth:2,flexDirection:'column',backgroundColor:'#ffffff',justifyContent:'space-between', alignItems:'center'}}> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'red'}}></View> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'black'}}></View> <View style={{height:100,width:100,borderRadius:50,backgroundColor:'blue'}}></View> </View>
![]()
|
![]()
|
justifyContent:'space-between' | justifyContent:'space-around' |
下面实现一个具体的例子,效果以下:
这是一个表单页面,从这个图能够得出:
1. 外层是主轴按照column排列。行元素撑满一行。
2. 行元素高度固定,主轴按row排列,次轴的排列应该居中。
3. 行元素有内衬,有分割线。
4. 行元素内应该分左右两部分,分别左右对齐。
根据这几点,咱们能够大概写出这样的布局:
class Layout extends Component { render() { return ( <View style={{flex:1,backgroundColor:'#dddddd',flexDirection:'column',justifyContent:'center'}}> <View style={LayoutStyles.row}> <Text style={{flex:1}}>真实姓名</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>John</Text> </View> </View> <View style={LayoutStyles.row}> <Text>手机号码</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>13812345678</Text> </View> </View> </View> ); } } const LayoutStyles = StyleSheet.create({ row: { backgroundColor:'#ffffff', height:47, flexDirection:'row', alignItems:'center', borderBottomWidth:0.5, borderBottomColor:'#dddddd', paddingHorizontal: 15 } });
这里能够看到, 在“手机号码”这一行内,用两个子元素Text和View分别设置flex:1来撑满行元素,而后设置view的末端对齐。
而“真实姓名”这一行只对view设置了flex:1,也达到了这个效果。
经过给view加上border看一下:
能够看出,若是在一个容器内,若是元素没有设置flex,那么默认会根据该元素的内容自动撑开宽度,而设置了flex:1的元素则会占满剩余的空间。
那么这里给 “真实姓名”这行的右边部分留下较大的空间,由于这里要放一个输入框,留下较大的区域能够方便它点中以获取焦点输入。
borderWidth问题
这样作使用borderWidth:0.5,这种写法在ios上是能够正常显示,可是在部分Android机型上显示异常。这个问题可使用 StyleSheet.hairlineWidth 来避免这个问题。
这里分割线使用了行元素的下边框来作,其实也能够吧分割线做为一个单独的子元素来绘制,好比:
<View style={{height:1,backgroundColor:'#dddddd'}}></View>
分割线问题
跟效果图对比行元素的分割线没有撑满,而是随行内容同样存在内衬。这个问题,若是采用上面的方法把分割线做为子元素,则能够解决。
若是使用边框的话,能够在行元素内再包一层View,外层View设置padding,内层view设置borderBottomWidth便可。
最终代码:
class Layout extends Component { render() { return ( <View style={{flex:1,backgroundColor:'#dddddd',flexDirection:'column',justifyContent:'center'}}> <View style={LayoutStyles.row}> <View style={LayoutStyles.rowContainer}> <Text>真实姓名</Text> <View style={{flex:1,alignItems:'flex-end',height:47}}> <TextInput style={LayoutStyles.inputTextName} underlineColorAndroid={'blue'} keyboardType={'default'} placeholder='请输入' placeholderTextColor='#999999' defaultValue={'laochan'} maxLength={10} /> </View> </View> </View> <View style={LayoutStyles.row}> <View style={LayoutStyles.rowContainer}> <Text style={{flex:1}}>手机号码</Text> <View style={{flex:1,alignItems:'flex-end'}}> <Text style={{color:'#999999'}}>13812345678</Text> </View> </View> </View> </View> ); } } const LayoutStyles = StyleSheet.create({ row: { backgroundColor:'#ffffff', height:47, paddingHorizontal: 15 }, rowContainer: { flex: 1, flexDirection:'row', alignItems:'center', borderBottomWidth:StyleSheet.hairlineWidth, borderBottomColor:'#dddddd', }, inputTextName: { flex:1, padding:0, fontSize:14, color: '#999999', textAlign: 'right', marginRight: 10 } });
参考资源:
http://reactnative.cn/docs/0.44/layout-with-flexbox.html#content
布局样式属性:http://reactnative.cn/docs/0.44/layout-props.html
flex布局:http://www.ruanyifeng.com/blog/2015/07/flex-examples.html