2. React Native布局基础与视图Style

4,183 阅读8分钟

React-Native布局基础

样式style

所有的核心组件都支持名为style的属性。此属性是一个JS对象,工作原理类似于CSS。

一般使用StyleSheet.create来集中创建样式以保持代码整洁。通常会让组件接收一个style的属性以便用于子组件。

const styles = StyleSheet.create({
  bigBlue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

宽与高

可以简单通过设置widthheight来指定组件的宽高。RN中尺寸没有单位,是相对于屏幕密度独立的单位点。


FlexBox Layout

可变尺寸flex

在组件样式中使用flex以使组件可以基于可用空间灵活伸缩。

flex默认在垂直方向进行伸缩,可以根据flexDirection来指定伸缩方向(水平方向为row)。flex可以接收一个参数。

父组件会在flex排布方向上,对所有子组件的flex值求和,然后把整体的尺寸按子组件对应flex值的比例进行分配。

flex的四种取值:

  • row
  • column,默认值
  • row-reverse,水平反向
  • column-reverse,垂直反向
<View style={{flex: 1, flexDirection: 'row'}}>
	<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
	<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
    <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>

布局方向

React-Native默认采用从左往右方向布局

Justify Content: justifyContent定义在容器内部主轴方向上如何排布子组件

  • flex-start: 默认值,从容器主轴起始位置开始排布
  • flex-end: 从容器主轴末尾位置开始排布
  • center: 子组件居中排布
  • space-between: 子组件之间等间距,不会在主轴两端设置额外的边距
  • space-around: 子组件之间等间距,且主轴两边各留出1/2间距值
  • space-evenly: 子组件与主轴两边的边距均相等

Align Items: alignItems定义在容器副轴(主轴交叉轴)方向上如何排布子组件。该效果与justifyContent是类似的。

:此属性要求在容器主轴的副轴上,每一行的子组件至少要存在一个高度值。如果在一行上所有的子组件都未指定高度,则该行子组件都不会被显示。合理设置alignItems,可以做到各子组件尺寸的相互参照。

  • stretch: 默认值,组件副轴方向尺寸,取该行整体的最大尺寸。此属性生效,对应组件在容器副轴方向不可设置固定尺寸值
  • flex-start: 从组件所在行的副轴方向起点开始布局
  • flex-end: 从组件所在行的副轴方向终点开始布局
  • center: 在组件所在行副轴方向居中
  • baseline: 在组件所在行的副轴方向基线对齐。每个子组件可以设置自身基线以便父容器用于布局

Align Self

alignSelfalignItems有相同的取值类型,不同的是此属性定义可以让子组件在父容器中在副轴方向独立于整体的排布方式而拥有单独的排布方式。例如,在某行上单一的子组件在该行居中,而其他同行的子组件起点对齐。

Align Content

当子组件排布支持换行(flexWrap: true)时,通过alignContent属性定义多行内容在副轴方向上的排布方式。

  • flex-start: 副轴方向起点对齐
  • flex-end: 副轴方向终点对齐(终点指该行子组件最大的尺寸位置)
  • stretch: 副轴方向铺满整行(副轴方向设置固定尺寸,则此属性不生效)
  • center: 副轴方向居中排布
  • space-between: 贴紧两边,等行间距排布
  • space-around: 两边留白,等行间距。留白为行间距一半。

注意: 此属性只有父容器支持子组件多行排布时才会生效。如果同时设置了alignItems与此属性,布局可能不正确。不要在设置了alignItems的同时设置alignContentspace-betweenspace-aroundstretch。此时系统计算的各行尺寸与该行最大尺寸的组件的尺寸并不一致。

Flex Wrap

flexWrap用于定义当子组件在主轴上布局超出父容器尺寸时是否需要换行。当允许换行时,可以通过alignContent控制多行内容在副轴上如何布局。

枚举类型:wrap(支持换行), nowrap(不换行)

Flex Basis, Grow, Shrink

flexGrow: 当主轴方向布局完所有的子组件后还有剩余空间时,是否对某个子组件进行放大。多个子组件同时设置此属性时,剩余空间将按比例进行分摊。此数值总和小于1时,只分摊对应比例的剩余空间。

flexShrink: 当主轴方向布局空间不足时,对指定的子组件尺寸进行压缩,取值范围0~1,默认值为1(不压缩)。如果父容器支持换行,此属性不起作用。

flexBasis: 相当于在主轴方向给定固定数值(直接设置固定width&height)。


View的Style属性

背景色与透明度
  • backgroundColor:视图背景色
  • opacity:不透明度
Direction

direction属性用来定义子组件在水平方向的布局流方向。默认会从上一级继承。可以设置为ltr(从左至右,默认)或rtl(从右至左)。

经测试,不论设置为何种方向,left始终等同于startright始终等同于end

Offset

设置组件的坐标偏移值。

  • top: 顶部偏移量
  • bottom: 底部偏移量
  • left/start: 距起点边界偏移量
  • right/end: 距终点边界偏移量

同一方向上同时设置了相反的两个偏移值,则只有距离轴线起点边界的值会生效。例如,同时设置leftright,则只采用left的值。

Margin

Margin是指当组件自身尺寸可变时,距指定边界的保留距离。当指定方向的尺寸固定时,设置margin相当于设置偏移量,且只有沿轴线布局方向起始边界的属性设置有效。例如:子组件的宽度固定,水平方向的布局为ltr,则只有设置marginStart/marginTop会对该组件有效,正值为向正向偏移,负值向反向偏移。

  • marginTop: 当自身垂直方向尺寸可变时,距离顶部的保留距离
  • marginBottom:当自身垂直方向尺寸可变时,距离底部的保留距离
  • marginLeft/marginStart:当自身水平方向尺寸可变时,距离左边的保留距离
  • marginRight/marginEnd:当自身水平方向尺寸可变时,距离右边的保留距离
  • marginHorizontal: 水平方向两边的边距,相当于设置等值的marginLeftmarginRight
  • marginVertical: 竖直方向两边的边距,相当于设置等值的marginTopmarginBottom
  • margin:当自身尺寸水平/竖直方向均可变时,设置自身内容区域距四边的等值边距
Padding

padding用于指定组件内部布局内容的边界保留距离。该边界距离不计入布局子组件的区域。例如,组件宽度为300,指定paddingLeft: 50, paddingRight: 50,则实际可布局的宽度为200.

  • paddingTop: 顶部留白
  • paddingBottom: 底部留白
  • paddingLeft/paddingStart: 距起点边界留白
  • paddingRight/paddingEnd: 距终点边界留白
  • paddingHorizontal: 水平方向边界留白,相当于设置等值的paddingLeftpaddingRight
  • paddingVertical: 竖直方向边界留白,相当于设置等值的paddingToppaddingBottom
  • padding: 边界留白,相当于设置四边的边界等值留白
宽高
  • width: 宽
  • height: 高
  • minWidth: 最小宽度
  • maxWidth: 最大宽度,仅设置此值,宽度取0
  • minHeight: 最小高度
  • maxHeight: 最大高度,仅设置此值,高度取0

绝对位置与相对位置

position:枚举类型,取值:

  • absolute:如果想要设置某个组件在其父组件中的位置绝对固定,可以将position设置为此值
  • relative:在RN中所有组件的位置默认都是相对的。可以通过组件树(component tree)来布局各个组件之间的相对位置关系

弹性布局相关属性

具体属性说明见上述Flexbox Layout

  • flex
  • flexDirection
  • justifyContent
  • alignItems
  • alignContent
  • alignSelf
  • flexGrow
  • flexShrink
  • flexWrap

View的边界样式设置属性

  • borderWidth:边线宽度
  • borderStyle:边线类型,分为:solid(实线),dotted(点线),dashed(虚线)
  • borderTopWidth:顶部边线宽度
  • borderBottomWidth:底部边线宽度
  • borderLeftWidth:左边边线宽度
  • borderRightWidth:右边边线宽度
  • borderColor:边线颜色
  • borderTopColor:顶部边线颜色
  • borderBottomColor:底部边线颜色
  • borderLeftColor/borderStartColor:左边边线颜色
  • borderRightColor/borderLeftColor:右边边线颜色
  • borderRadius:圆角半径。注,如果圆角不可见,可以尝试设置overflow: 'hidden'
  • borderTopLeftRadius/borderTopStartRadius:左上角圆角半径
  • borderTopRightRadius/borderTopEndRadius:右上角圆角半径
  • borderBottomLeftRadius/borderBottomStartRadius:左下角圆角半径
  • borderBottomRightRadius/borderBottomEndRadius:右下角圆角半径

注:TextInput不支持设置边线宽度和圆角


React Native中父组件访问子组件

React Native中,父组件访问自身的子组件,需要在父组件的render方法中为子组件指定引用关系,通过引用来访问。有如下两种方式:

  1. 通过回调函数将子组件设置为父组件的成员属性

    render() {
        return (
            // 将该子组件设置到自身的someChildView属性上,通过this.someChildView访问
            <View ref={ view => this.someChildView = view } >
            </View>
        )
    }
    
  2. 为子组件设置标识符,通过父组件的refs集合来访问

    render() {
        return (
            // 在需要使用到此子组件时,通过this.refs.someIdentifier来访问此子组件
            <View ref='someIdentifier' />
        )
    }