鸿蒙应用开发从入门到实战(二十三):一文搞懂ArkUI弹性布局

大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容、欢迎关注!

ArkUI提供了各种布局组件用于界面布局,本文研究使用Flex组件实现弹性布局。

一、概述

弹性布局(Flex )的效果类似于线性布局(Column /Row),也会使子元素呈线性排列,但是弹性布局在子元素的排列、对齐和剩余空间的分配等方面更加灵活。

二、参数

Flex组件的参数定义如下,下面逐一介绍每个属性

typescript 复制代码
Flex(value?: { direction?: FlexDirection, justifyContent?: FlexAlign, alignItems?: ItemAlign, wrap?: FlexWrap, alignContent?: FlexAlign })

2.1 布局方向(direction)

direction用于设置Flex 容器的布局方向,即子元素的排列方向,其类型FlexDirection为枚举类型,可选的枚举值如下

示例代码

pages/component/layout目录下新建flex目录,新建DirectionPage.ets文件

typescript 复制代码
@Entry
@Component
struct DirectionPage {
  build() {
    Column({ space: 50 }) {
      Flex({ direction: FlexDirection.ColumnReverse }) {
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle4()
        Text('2')
          .width(100)
          .height(100)
          .itemTextStyle4()
        Text('3')
          .width(100)
          .height(100)
          .itemTextStyle4()
      }
      .height(350)
      .width(350)
      .flexStyle4()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle4() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle4() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

Flex 容器中也有主轴交叉轴 两个概念,其中主轴方向与direction一致,交叉轴与主轴垂直,具体方向如下

2.2 主轴排列方式(justifyContent)

justifyContent 参数的作用同Column/Row 容器的justifyContent()完全相同,也是用于设置子元素在主轴方向 的排列方式,其类型同样为FlexAlign,可选的枚举值如下

示例代码

pages/component/layout/flex目录,新建JustifyContentPage.ets文件

typescript 复制代码
@Entry
@Component
struct JustifyContentPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        justifyContent: FlexAlign.Start
      }) {
        Text('1')
          .width(50)
          .height(50)
          .itemTextStyle5()
        Text('2')
          .width(50)
          .height(50)
          .itemTextStyle5()
        Text('3')
          .width(50)
          .height(50)
          .itemTextStyle5()
      }.height(50)
      .width(300)
      .flexStyle5()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle5() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle5() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

2.3 交叉轴对齐方式(alignItems)

alignItems参数的作用同Column/Row 容器的alignItems()相同,也是用于设置子元素在交叉轴 的对齐方式。但该参数的类型与Column/Row 容器的alignItems()方法不同,为ItemAlign,可选的枚举值有

示例代码

pages/component/layout/flex目录,新建AlignItemsFlexPage.ets文件

typescript 复制代码
@Entry
@Component
struct AlignItemsFlexPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        alignItems: ItemAlign.Baseline
      }) {
        Text('Beyond')
          .width(100)
          .height(100)
          .itemTextStyle6()
        Text('章')
          .width(100)
          .height(200)
          .itemTextStyle6()
        Text('章')
          .width(100)
          .height(150)
          .itemTextStyle6()
      }.height(350)
      .width(350)
      .flexStyle6()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle6() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle6() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

2.4 布局换行(列)(wrap)

默认情况下,Flex 容器的子组件,都排在一条线(主轴)上。当子组件在主轴方向的尺寸之和大于Flex 容器时,为适应容器尺寸,所有子组件的尺寸都会自动收缩 。如果需要保持子组件的尺寸不收缩,也可选择令子组件**换行(列)**显示。

wrap属性的作用就是控制如何换行,该属性的类型FlexWrap为枚举类型,可选的枚举值如下

示例代码

pages/component/layout/flex目录,新建WrapPage.ets文件

typescript 复制代码
@Entry
@Component
struct WrapPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        wrap: FlexWrap.WrapReverse
      }) {
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle7()
        Text('2')
          .width(100)
          .height(100)
          .itemTextStyle7()
        Text('3')
          .width(100)
          .height(100)
          .itemTextStyle7()
        Text('4')
          .width(100)
          .height(100)
          .itemTextStyle7()
        Text('5')
          .width(100)
          .height(100)
          .itemTextStyle7()
        Text('6')
          .width(100)
          .height(100)
          .itemTextStyle7()
      }.height(350)
      .width(350)
      .flexStyle7()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle7() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle7() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

2.5 交叉轴多行排列方式(alignContent)

Flex 容器中包含多行(列)时,可使用alignContent设置多行在交叉轴的排列方式,该属性的类型为FlexAlign,可选的枚举值如下

示例代码

pages/component/layout/flex目录,新建AlignContentPage.ets文件

typescript 复制代码
@Entry
@Component
struct AlignContentPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        wrap: FlexWrap.Wrap,
        alignContent: FlexAlign.SpaceAround,
      }) {
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle8()
        Text('2')
          .width(100)
          .height(100)
          .itemTextStyle8()
        Text('3')
          .width(100)
          .height(100)
          .itemTextStyle8()
        Text('4')
          .width(100)
          .height(100)
          .itemTextStyle8()
        Text('5')
          .width(100)
          .height(100)
          .itemTextStyle8()
        Text('6')
          .width(100)
          .height(100)
          .itemTextStyle8()
      }.height(350)
      .width(350)
      .flexStyle8()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle8() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle8() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

三、子组件常用属性

3.1 交叉轴对齐(alignSelf)

Flex容器的子组件可以使用alignSelf()方法单独设置自己的交叉轴对齐方式,并且其优先级高于Flex 容器alignItems。具体效果如下

说明:

alignSelf()的参数类型和alignItems()相同,均为ItemAlign枚举类型,且各枚举值的含义也完全相同。

代码

typescript 复制代码
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) {
  Text('1')
    .width(100)
    .height(100)
    .itemTextStyle()
  Text('2')
    .width(100)
    .height(200)
    .itemTextStyle()
  Text('3')
    .width(100)
    .height(150)
    .itemTextStyle()
    .alignSelf(ItemAlign.End) //单独设置交叉轴对齐方式
}.height(300)
.width('95%')
.flexStyle()

效果

示例代码

pages/component/layout/flex目录,新建AlignSelfPage.ets文件

typescript 复制代码
@Entry
@Component
struct AlignSelfPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        alignItems: ItemAlign.Start
      }) {
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle9()
        Text('2')
          .width(100)
          .height(200)
          .itemTextStyle9()
        Text('3')
          .width(100)
          .height(150)
          .itemTextStyle9()
          .alignSelf(ItemAlign.End)
      }.height(350)
      .width(350)
      .flexStyle9()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle9() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle9() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

3.2 自适应伸缩

弹性布局的显著特点之一是子组件 沿主轴 方向的尺寸具有弹性 ,即子组件的大小能够随着Flex容器尺寸的变化而自动伸缩 。这种弹性特性使得Flex布局能够使子组件更灵活地适应不同的屏幕尺寸和设备。和自适应伸缩的相关的属性有flexShrinkflexGrowflexBasis,下面逐一介绍

3.2.1 flexShrink 压缩

flexShrink用于设置父容器空间不足时,子组件的压缩比例,尺寸的具体计算逻辑如下

代码

typescript 复制代码
//Flex容器主轴尺寸为240,子组件主轴尺寸之和为100*3=300
Flex() {
  //尺寸=100
  Text('1')
    .width(100)
    .height(100)
    .flexShrink(0) //不压缩

  //主轴尺寸=100-(300-240)*(1/3)=80
  Text('2')
    .width(100)
    .height(100)
    .flexShrink(1) //压缩比例为1

  //主轴尺寸=100-(300-240)*(2/3)=60
  Text('3')
    .width(100)
    .height(100)
    .flexShrink(2) //压缩比例为2
  
}.height(150)
.width(240)

效果

示例代码

pages/component/layout/flex目录,新建FlexShrinkPage.ets文件

typescript 复制代码
@Entry
@Component
struct FlexShrinkPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        alignItems: ItemAlign.Center
      }) {
        //尺寸=100
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle10()
          .flexShrink(0) //不压缩

        //主轴尺寸=100-(300-240)*(1/3)=80
        Text('2')
          .width(100)
          .height(100)
          .itemTextStyle10()
          .flexShrink(1) //压缩比例为1

        //主轴尺寸=100-(300-240)*(2/3)=60
        Text('3')
          .width(100)
          .height(100)
          .itemTextStyle10()
          .flexShrink(2) //压缩比例为2

      }.height(150)
      .width(240)
      .flexStyle10()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle10() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle10() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

3.2.2 flexGrow 拉伸

flexGrow用于设置父容器空间充足时,组件瓜分剩余空间的比例,尺寸的具体计算逻辑如下

代码

typescript 复制代码
Flex() {
  //尺寸=100
  Text('1')
    .width(100)
    .height(100)
    .flexGrow(0) //不拉伸

  //主轴尺寸=100+(360-300)*(1/3)=120
  Text('2')
    .width(100)
    .height(100)
    .flexGrow(1) //拉伸比例为1

  //主轴尺寸=100+(360-300)*(2/3)=140
  Text('3')
    .width(100)
    .height(100)
    .flexGrow(2) //拉伸比例为2

}.height(150)
.width(360)

效果

示例代码

pages/component/layout/flex目录,新建FlexGrowPage.ets文件

typescript 复制代码
@Entry
@Component
struct FlexGrowPage {
  build() {
    Column({ space: 50 }) {
      Flex({
        direction: FlexDirection.Row,
        alignItems: ItemAlign.Center
      }) {
        //尺寸=100
        Text('1')
          .width(100)
          .height(100)
          .itemTextStyle11()
          .flexGrow(0) //不拉伸

        //主轴尺寸=100+(360-300)*(1/3)=120
        Text('2')
          .width(100)
          .height(100)
          .itemTextStyle11()
          .flexGrow(1) //拉伸比例为1

        //主轴尺寸=100+(360-300)*(2/3)=140
        Text('3')
          .width(100)
          .height(100)
          .itemTextStyle11()
          .flexGrow(2) //拉伸比例为2

      }.height(150)
      .width(360)
      .flexStyle11()

    }.width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Extend(Text) function itemTextStyle11() {
  .textAlign(TextAlign.Center)
  .fontColor(Color.White)
  .fontSize(40)
  .fontWeight(FontWeight.Bold)
  .backgroundColor('#008a00')
  .borderWidth(1)
}

@Extend(Flex) function flexStyle11() {
  .backgroundColor('#f5f5f5')
  .borderWidth(1)
}

3.2.3 flexBasis

flexBasis用于设置子组件沿主轴方向的尺寸,相当于width或者height的作用。若设置了flexBasis,则以flexBasis为准,否则以widht或者height为准。

《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业级项目实战等原创内容,防止迷路,欢迎关注!

相关推荐
猫林老师5 小时前
OpenHarmony南向开发环境搭建 - 深入理解Ubuntu、DevEco Device Tool与HPM
linux·运维·ubuntu·harmonyos·openharmony
Bert丶seven5 小时前
鸿蒙Harmony实战开发教学Day1-IDE新版本安装篇
华为·harmonyos·arkts·鸿蒙·鸿蒙系统·arkui·开发教学
2501_9197490314 小时前
鸿蒙:用Toggle组件实现选择框、开关样式
华为·harmonyos
熊猫钓鱼>_>14 小时前
ArkTS 深度解析:鸿蒙生态的基石与未来之路
华为·harmonyos
郝晨妤20 小时前
鸿蒙List组件通过拖拽改变排序
华为od·华为·harmonyos·鸿蒙
大雷神1 天前
windows系统实操Flutter鸿蒙环境搭建
华为·harmonyos
2503_928411561 天前
10.9 了解鸿蒙生态
华为·harmonyos
安卓开发者1 天前
FFRT的核心并发范式与样例概览
harmonyos