鸿蒙学习实战之路-弹性布局 Flex 全攻略

鸿蒙学习实战之路-弹性布局 Flex 全攻略

最近好多朋友问我:"我想在鸿蒙里做个漂亮的页面布局,但 Row 和 Column 太死板了,有没有更灵活的方式?"_

今天这篇,我就手把手带你搞定弹性布局(Flex)——鸿蒙里最灵活的布局神器!全程都是能跑的代码和避坑指南,看完你就能轻松实现各种复杂布局~ o(∩_∩)o


一、什么是弹性布局?

弹性布局(Flex)就像一个会伸缩的容器,能自动帮你调整里面元素的位置和大小。想象一下,你有一个弹性口袋,不管里面装多少东西,它都能自动分配空间,让东西摆得整整齐齐~

核心概念

  • 主轴:元素排列的方向(水平/垂直)
  • 交叉轴:垂直于主轴的方向

这两个轴是理解 Flex 的关键,咱们先记住它们~


二、快速上手:写一个简单的 Flex 布局

咱们先写一个最基础的弹性布局,感受一下它的威力!

@Entry
@Component
struct FlexBasicExample {
  build() {
    Column() {
      // 创建一个水平方向的Flex容器
      Flex() {
        Text('我是第一个元素').width('33%').height(50).backgroundColor('#F5DEB3')
        Text('我是第二个元素').width('33%').height(50).backgroundColor('#D2B48C')
        Text('我是第三个元素').width('33%').height(50).backgroundColor('#F5DEB3')
      }
      .height(70)
      .width('90%')
      .padding(10)
      .backgroundColor('#AFEEEE')
    }
    .width('100%')
    .height('100%')
  }
}

效果:三个元素会自动在水平方向上排列,每个占容器宽度的 33%~

🥦 西兰花小贴士
Flex 默认是水平方向(Row)排列的,这也是最常用的布局方式~


三、布局方向:灵活控制元素排列

刚才咱们用的是默认的水平方向,其实 Flex 支持四种布局方向:

1. 水平方向(默认)

Flex({ direction: FlexDirection.Row }) {
  // 元素内容
}

2. 水平反向

Flex({ direction: FlexDirection.RowReverse }) {
  Text('1').width('33%').height(50).backgroundColor('#F5DEB3')
  Text('2').width('33%').height(50).backgroundColor('#D2B48C')
  Text('3').width('33%').height(50).backgroundColor('#F5DEB3')
}

效果:元素从右往左排列~

3. 垂直方向

Flex({ direction: FlexDirection.Column }) {
  // 元素内容
}

4. 垂直反向

Flex({ direction: FlexDirection.ColumnReverse }) {
  // 元素内容
}

🥦 西兰花警告
方向设置会影响主轴和交叉轴的方向哦!比如垂直方向时,主轴变成了垂直方向,交叉轴变成了水平方向~


四、布局换行:处理元素太多的情况

如果元素总宽度超过了容器宽度,Flex 默认会压缩元素。但咱们可以设置换行,让元素自动换行排列~

1. 不换行(默认)

Flex({ wrap: FlexWrap.NoWrap }) {
  Text('1').width('50%').height(50).backgroundColor('#F5DEB3')
  Text('2').width('50%').height(50).backgroundColor('#D2B48C')
  Text('3').width('50%').height(50).backgroundColor('#F5DEB3')
}

效果:三个元素都被压缩在一行里~

2. 换行

Flex({ wrap: FlexWrap.Wrap }) {
  Text('1').width('50%').height(50).backgroundColor('#F5DEB3')
  Text('2').width('50%').height(50).backgroundColor('#D2B48C')
  Text('3').width('50%').height(50).backgroundColor('#D2B48C')
}

效果:第三个元素自动换到了下一行~

3. 反向换行

Flex({ wrap: FlexWrap.WrapReverse }) {
  // 元素内容
}

五、主轴对齐:控制元素在主轴上的位置

主轴对齐是 Flex 最常用的功能之一,它能控制元素在主轴方向上的排列方式。咱们来看看常用的几种:

1. 起始对齐(默认)

Flex({ justifyContent: FlexAlign.Start }) {
  Text('1').width('20%').height(50).backgroundColor('#F5DEB3')
  Text('2').width('20%').height(50).backgroundColor('#D2B48C')
  Text('3').width('20%').height(50).backgroundColor('#F5DEB3')
}

效果:元素从主轴起始端排列~

2. 居中对齐

Flex({ justifyContent: FlexAlign.Center }) {
  // 元素内容
}

效果:元素在主轴方向居中~

3. 末尾对齐

Flex({ justifyContent: FlexAlign.End }) {
  // 元素内容
}

4. 均匀分布

Flex({ justifyContent: FlexAlign.SpaceBetween }) {
  // 元素内容
}

效果:元素之间距离相等,两端贴边~

5. 环绕分布

Flex({ justifyContent: FlexAlign.SpaceAround }) {
  // 元素内容
}

效果:元素之间距离相等,两端距离是中间的一半~

6. 等间距分布

Flex({ justifyContent: FlexAlign.SpaceEvenly }) {
  // 元素内容
}

效果:所有间距都相等~


六、交叉轴对齐:控制元素在交叉轴上的位置

交叉轴对齐控制元素在垂直于主轴方向上的排列。Flex 容器和子元素都可以设置交叉轴对齐~

1. 容器设置交叉轴对齐

Flex({ alignItems: ItemAlign.Center }) {
  Text('1').width('33%').height(30).backgroundColor('#F5DEB3')
  Text('2').width('33%').height(40).backgroundColor('#D2B48C')
  Text('3').width('33%').height(50).backgroundColor('#F5DEB3')
}
.size({ width: '90%', height: 80 })

效果:不同高度的元素在交叉轴上居中对齐~

常用的交叉轴对齐方式

  • ItemAlign.Start:交叉轴起始端对齐
  • ItemAlign.Center:交叉轴居中对齐
  • ItemAlign.End:交叉轴末尾对齐
  • ItemAlign.Stretch:拉伸填充交叉轴
  • ItemAlign.Baseline:文本基线对齐

2. 子元素单独设置交叉轴对齐

咱们还可以给某个子元素单独设置交叉轴对齐,覆盖容器的设置~

Flex() {
  Text('1').width('33%').height(30).backgroundColor('#F5DEB3')
    .alignSelf(ItemAlign.End)  // 单独设置这个元素在交叉轴末尾对齐
  Text('2').width('33%').height(40).backgroundColor('#D2B48C')
  Text('3').width('33%').height(50).backgroundColor('#F5DEB3')
}

🥦 西兰花小贴士
alignSelf 是子元素的属性,可以单独控制某个元素的交叉轴对齐方式~


七、实战案例:实现一个导航栏

咱们来做个实战案例——实现一个手机应用常见的导航栏布局~

@Entry
@Component
struct FlexNavBarExample {
  build() {
    Column() {
      // 导航栏容器
      Flex() {
        // 左侧返回按钮
        Text('←').fontSize(24)
          .width(40).height(40)
          .textAlign(TextAlign.Center)
          .alignSelf(ItemAlign.Center)

        // 标题(自动占满剩余空间)
        Text('弹性布局教程')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .flexGrow(1)  // 自动占满剩余空间
          .textAlign(TextAlign.Center)

        // 右侧更多按钮
        Text('⋮').fontSize(24)
          .width(40).height(40)
          .textAlign(TextAlign.Center)
          .alignSelf(ItemAlign.Center)
      }
      .width('100%')
      .height(56)
      .padding({ left: 16, right: 16 })
      .backgroundColor('#FFFFFF')
      .borderBottom({ width: 1, color: '#E5E5E5' })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

解析

  • 使用 flexGrow(1) 让标题自动占满剩余空间
  • 使用 alignSelf 让按钮垂直居中
  • 整体实现了一个常见的导航栏布局~

🥦 西兰花警告
flexGrow 属性非常好用,它能让元素自动分配剩余空间。但要注意,只有在主轴有剩余空间时才会生效哦!


八、高级技巧:Flex 的更多用法

1. 自适应拉伸

使用 flexGrow 可以让元素自动分配剩余空间,实现自适应布局~

Flex() {
  Text('固定宽度').width(100).height(50).backgroundColor('#F5DEB3')
  Text('自适应宽度').height(50).backgroundColor('#D2B48C')
    .flexGrow(1)  // 占满剩余空间
  Text('固定宽度').width(100).height(50).backgroundColor('#F5DEB3')
}

2. 嵌套 Flex

咱们可以在 Flex 容器里再放 Flex 容器,实现更复杂的布局~

Flex({ direction: FlexDirection.Column }) {
  // 顶部栏
  Flex() {
    // 顶部栏内容
  }

  // 中间内容区
  Flex() {
    // 中间内容
  }
  .flexGrow(1)  // 占满剩余空间

  // 底部栏
  Flex() {
    // 底部栏内容
  }
}

九、避坑指南

1. 方向设置影响轴的方向

  • 水平方向:主轴是水平,交叉轴是垂直
  • 垂直方向:主轴是垂直,交叉轴是水平

2. 对齐方式的优先级

  • 子元素的 alignSelf 优先级高于容器的 alignItems
  • 主轴对齐和交叉轴对齐是独立的,需要分别设置

3. 换行和不换行的区别

  • NoWrap:元素会被压缩
  • Wrap:元素会自动换行

4. flexGrow 的使用场景

  • 只有在主轴有剩余空间时才会生效
  • 可以同时给多个元素设置,按比例分配空间

十、额外案例:实现一个商品卡片

咱们来实现一个电商应用中常见的商品卡片布局,只使用色块和 Flex 布局~

@Entry
@Component
struct FlexProductCardExample {
  build() {
    Column() {
      Text('商品卡片示例')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin(20)

      // 商品卡片容器
      Flex({ direction: FlexDirection.Column }) {
        // 商品图片区域(色块模拟)
        Stack() {
          Text('商品图片')
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .fontColor(Color.White)
        }
        .width('100%')
        .height(200)
        .backgroundColor('#D2B48C')


        // 商品信息区域
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start }) {
          // 商品标题
          Text('这是一个非常好用的商品')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
            .margin(8)

          // 商品描述
          Text('这个商品真的很不错,买了不会后悔的~')
            .fontSize(14)
            .fontColor('#666666')
            .margin(12)

          // 价格和购买按钮区域
          Flex() {
            // 价格
            Text('¥99.99')
              .fontSize(20)
              .fontWeight(FontWeight.Bold)
              .fontColor('#FF4444')
              .flexGrow(1)

            // 购买按钮
            Text('立即购买')
              .width(100)
              .height(36)
              .textAlign(TextAlign.Center)
              .fontColor(Color.White)
              .backgroundColor('#FF4444')
              .borderRadius(18)
          }
        }
      }
      .width('90%')
      .backgroundColor(Color.White)
      .borderRadius(12)
      .shadow({
        radius: 4,
        color: '#00000020',
        offsetX: 0,
        offsetY: 2
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

代码解析

  1. 整体使用垂直方向的 Flex 容器作为卡片主体
  2. 顶部用 Stack 和色块模拟商品图片区域
  3. 中间使用垂直 Flex 容器存放商品信息
  4. 底部使用水平 Flex 容器实现价格和购买按钮的布局,价格区域用flexGrow(1)自动占满剩余空间
  5. 最后添加圆角和阴影效果,让卡片更立体

这个案例展示了如何用 Flex 布局实现一个常见的商品卡片,代码简单易懂,只使用了色块和文本,没有依赖图片~

🥦 西兰花小贴士
商品卡片是电商应用的核心组件,掌握这个布局可以举一反三,实现更多类似的卡片式设计~


写在最后

恭喜你!现在你已经掌握了弹性布局(Flex)的核心用法~ 这是鸿蒙开发中最灵活的布局方式,几乎能满足所有的布局需求~

下一步学习建议

  • 尝试用 Flex 实现一个完整的页面布局
  • 结合其他组件(如 Scroll、Swiper)使用 Flex
  • 探索 Flex 的更多高级属性

📚 推荐资料

我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

posted @ 2025-12-23 23:38  时间煮鱼  阅读(3)  评论(0)    收藏  举报