鴻蒙學習實戰之路-彈性佈局 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 全攻略_Text

🥦 西蘭花小貼士: 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')
}

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

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_導航欄_02

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')
}

效果:三個元素都被壓縮在一行裏~

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Self_03

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')
}

效果:第三個元素自動換到了下一行~

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Text_04

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')
}

效果:元素從主軸起始端排列~

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Text_05

2. 居中對齊

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

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

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Text_06

3. 末尾對齊

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

4. 均勻分佈

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

效果:元素之間距離相等,兩端貼邊~

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Self_07

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 })

效果:不同高度的元素在交叉軸上居中對齊~

鴻蒙學習實戰之路-彈性佈局 Flex 全攻略_Self_08

常用的交叉軸對齊方式

  • 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 的更多高級屬性

📚 推薦資料

  • 鴻蒙官方 Flex 文檔

我是鹽焗西蘭花, 不教理論,只給你能跑的代碼和避坑指南。 下期見!🥦