React Native 布局详解

 

一、概述

 

一款优秀的APP离不开一个漂亮的UI,一个漂亮的UI又是由各种布局组合而成,因此APP的开发过程中,布局的实现是很重要的一部分。在React Native(以下简称RN)开发中,RN为我们提供了FlexBox(弹性框)进行布局,FlexBox功能十分强大,它提供了在不同尺寸设备上都能保持一致的布局方式,接下来我将从FlexBox着手详细讲解RN布局。

二、RN中的尺寸

在分析FlexBox之前,首先得清楚一个概念,即RN中的“宽、高、字体大小”。一个一个组件的高度和宽度决定了它在屏幕上的尺寸,也就是大小。在React Native中尺寸是没有单位的,表示的是与设备像素密度无关的逻辑像素点。

下面看一个简单例子:

  • RN中的布局

<View style={{height: 100, width: 300, margin: 20, backgroundColor:'#fab27b'}}>
    <Text style={ {fontSize:16,margin:20}}>尺寸</Text>
</View>
  • Android原生中的布局

<LinearLayout
    android:layout_width="300dp"
    android:layout_height="100dp"
    android:layout_margin="20dp"
    android:background="#fab27b">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:text="尺寸"
        android:textSize="16sp"/>
</LinearLayout>

最后效果图如下:左边为RN,下边为Android。

 

其实RN在android上运行时,View的宽300 高100 会被解释成宽300dp和高100dp,字体大小16会解释为16sp。

同时RN也为我们提供相关API来获取手机屏幕的大小。


var {height, width} = Dimensions.get('window');

三、RN之弹性宽高(Flex)

很多时候,我们都有让子组件填充父组件剩余空间这种需求,RN中为我们提供了Flex这种弹性布局样式。在组件样式中使用flex可以使其在可利用的空间中动态地扩张或收缩。

Flex样式与android中的layout_weight属性很类似,我们可以使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex值的比)。

具体可以看看如下实例:


<View style={{height:100, marginTop:10}}>
    <View style={{flex:1, backgroundColor: 'powderblue'}} />
    <View style={{flex:2, backgroundColor: 'skyblue'}} />
    <View style={{flex:3, backgroundColor: 'steelblue'}} />
</View>

效果图如下:

在使用flex的时候,有一个十分重要的注意点,即父布局需要有固定的宽高或者父布局也需要设置flex,否则,子组件是无法显示的,如下:

 


<View>
    <View style={{flex:1, backgroundColor: 'powderblue'}} />
    <View style={{flex:2, backgroundColor: 'skyblue'}} />
    <View style={{flex:3, backgroundColor: 'steelblue'}} />
</View>

由于无法知道外层view的宽高,所以子view的宽高也是无法确定的。

四、RN之Flexbox布局

RN为我们提供了强大的布局模式即Flexbox布局,使用这种布局可以简单快速地完成某个组件的子元素的布局,同时也可以在不同屏幕尺寸上提供一致的布局结构。Flexbox中有三个很重要的样式属性(flexDirection、alignItems和 justifyContent),使用这三个样式属性就已经能满足大多数布局需求。

  • flexDirection样式

flexDirection,它决定布局的主轴,确定子元素应该哪个轴进行排列。它可取值有:

valuedescription
row子元素是应该沿着水平轴方向排列
row-reverse子元素是应该沿着水平轴方向倒序排列
column子元素是应该沿着垂直轴方向排列
column-reverse子元素是应该沿着垂直轴方向倒序排列

默认情况下,flexDirection的取值为column,下面以实例来看看具体的效果:


<View style={{height:300, backgroundColor: '#b2d235',marginTop:10}}>
    <View style={{width: 80, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'skyblue'}} ><Text>布局二</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'steelblue'}} ><Text>布局三</Text></View>
</View>

如下图:

<View style={{height:100, backgroundColor: '#b2d235', flexDirection:'row', marginTop:10}}>
    <View style={{width: 80, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'skyblue'}} ><Text>布局二</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'steelblue'}} ><Text>布局三</Text></View>
</View>

<View style={{height:100, backgroundColor: '#b2d235', flexDirection:'row-reverse', marginTop:10}}>
    <View style={{width: 80, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'skyblue'}} ><Text>布局二</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'steelblue'}} ><Text>布局三</Text></View>
</View>

  • justifyContent样式

在组件的style中指定justifyContent可以决定其子元素沿着主轴的排列方式。例如子元素应该靠近主轴的起始端还是末尾段分布呢亦或应该均匀分布等等。它的可选项值如下,默认值为flex-start。

valuedescription
flex-start子元素沿着主轴方向上起始位置依次显示
center子元素沿着主轴方向上居中显示
flex-end子元素沿着主轴方向上末尾位置依次显示
space-around子元素在主轴方向上两侧间隔相等方式显示,因此元素之间的间隔比元素与边框的间隔大一倍。
space-between子元素在主轴方向上两端对齐,项目之间的间隔都相等。

<View style={{height:100, backgroundColor: '#b2d235', flexDirection:'row', marginTop:10}}>
    <View style={{width: 80, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'skyblue'}} ><Text>布局二</Text></View>
    <View style={{width: 80, height: 60, backgroundColor: 'steelblue'}} ><Text>布局三</Text></View>
</View>

具体显示如下图,第一个是如上布局显示状态。

 

  • alignItems样式

justifyContent决定子元素沿着主轴的排列方式,那么当然存在一个样式决定其子元素沿着次轴(与主轴垂直的轴)的排列方式,它就是alignItems样式。它的可选项值如下,默认值为flex-start。

valuedescription
flex-start子元素沿着次轴方向上起始位置依次显示
center子元素沿着次轴方向上居中显示
flex-end子元素沿着次轴方向上末尾位置依次显示
stretch子元素在次轴方向拉伸显示。

<View style={{height:70, backgroundColor: '#b2d235',
    flexDirection:'row', justifyContent:'flex-start', alignItems:'flex-start', marginTop:40}}>
    <View style={{width: 90, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 70, height: 40, backgroundColor: 'skyblue'}} ><Text>布局二</Text></View>
    <View style={{width: 50, height: 20, backgroundColor: 'steelblue'}} ><Text>布局三</Text></View>
</View>

具体显示如下图,第一个是如上布局显示状态。

 

需要注意的是alignItems值为stretch的情况,要使stretch选项生效的话,子元素在次轴方向上不能有固定的尺寸。如下:

 

能够熟练运用如上三个样式,基本上可以满足我们大多数的布局需求,如上部分仅只属于布局的最基础部分,要运用好布局,RN还提供了很多其他的样式。

五、其他重要布局样式

1. alignSelf

决定了元素在父元素的次轴方向的排列方式(此样式设置在子元素上),其值会覆盖父元素的alignItems的值。

可取值有 enum('auto', 'flex-start', 'flex-end', 'center', 'stretch')

例如:


<View style={{height:70, backgroundColor: '#b2d235',
    flexDirection:'row', justifyContent:'flex-start', alignItems:'center', marginTop:40}}>
    <View style={{width: 90, height: 60, backgroundColor: 'powderblue'}} ><Text>布局一</Text></View>
    <View style={{width: 70, height: 40, backgroundColor: 'skyblue', alignSelf:'flex-start'}} ><Text>布局二</Text></View>
    <View style={{width: 50, height: 20, backgroundColor: 'steelblue', alignSelf:'center'}} ><Text>布局三</Text></View>
    <View style={{width: 50, height: 40, backgroundColor: '#4e72b8', alignSelf:'flex-end'}} ><Text>布局四</Text></View>
    <View style={{width: 50, backgroundColor: '#2a5caa', alignSelf:'stretch'}} ><Text>布局五</Text></View>
</View>

显示如下:

 

2. flexWrap

该样式应用在父容器中,类似于android的流式布局。 可取值有enum('nowrap ', 'wrap', 'wrap-reverse')


nowrap:默认值,不换行
wrap:换行,第一行在上方
wrap-reverse:换行,第一行在下方。(和wrap相反)

例如:


<View style={{backgroundColor: '#6d8346',marginTop:10, flexDirection:'row', flexWrap:'wrap'}}>
    <View style={{width: 40, height: 40, backgroundColor: 'powderblue', margin:5}} ><Text>布局一</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'skyblue', margin:5}} ><Text>布局二</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'steelblue', margin:5}} ><Text>布局三</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'powderblue', margin:5}} ><Text>布局一</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'skyblue', margin:5}} ><Text>布局二</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'steelblue', margin:5}} ><Text>布局三</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'powderblue', margin:5}} ><Text>布局一</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'skyblue', margin:5}} ><Text>布局二</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'steelblue', margin:5}} ><Text>布局三</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'powderblue', margin:5}} ><Text>布局一</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'skyblue', margin:5}} ><Text>布局二</Text></View>
    <View style={{width: 40, height: 40, backgroundColor: 'steelblue', margin:5}} ><Text>布局三</Text></View>
</View>

显示如下:

 

3. position

position表示当前描述的位置是相对位置还是绝对定位的。可以取值为relative(默认值)或者absolute,与位置相关样式设置键还有:top、bottom、left、right。它们都是数值类型,表示描述的位置从左或者右多少位置显示,或者从上或者下多少位置显示,这些值只有当 position为absolute时才有效。 例如:


<View style={{height:100, backgroundColor: '#b2d235', marginTop:40}}>
    <View style={{width: 90, height: 60, backgroundColor: 'powderblue',position:'absolute'}} ><Text>布局一</Text></View>
    <View style={{width: 70, height: 40, backgroundColor: 'skyblue', position:'absolute', left: 100, top:10}} ><Text>布局二</Text></View>
    <View style={{width: 50, height: 20, backgroundColor: 'steelblue', position:'absolute', left: 100, top:60}} ><Text>布局三</Text></View>
</View>

显示如下:

 

4. 边框相关


borderWidth:边框宽度
borderLeftWidth:边框左边宽度
borderRightWidth:边框右边宽度
borderTopWidth:边框上边宽度
borderBottomWidth:边框下边宽度

5.外边距相关


margin:一个组件所有外边距的宽度,包括上下左右。
marginLeft:左边距宽度
marginRight:右边距宽度
marginTop:上边距宽度
marginBottom:下边距宽度
marginHorizontal:等价marginLeft和marginRight
marginVertical:等价marginTop和marginBottom

6、内边距相关


padding:一个组件所有内边距的宽度,包括上下左右。
paddingLeft:左边距宽度
paddingRight:右边距宽度
paddingTop:上边距宽度
paddingBottom:下边距宽度
paddingHorizontal:等价marginLeft和marginRight
paddingVertical:等价marginTop和marginBottom

六、参考链接

https://reactnative.cn/docs/0.49/height-and-width.html#content 

https://reactnative.cn/docs/0.49/layout-with-flexbox.html#content 

https://reactnative.cn/docs/0.49/layout-props.htmlhttp://www.ruanyifeng.com/blog/2015/07/flex-grammar.html https://blog.csdn.net/fengyuzhengfan/article/details/52090154

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值