鴻蒙學習實戰之路-層疊佈局 Stack 全攻略

最近好多朋友問我:"鴻蒙的佈局除了 Row、Column 和 Grid,還有沒有能讓元素疊在一起的?我想做個卡片懸浮效果,咋整啊?" _

今天這篇,我就手把手帶你搞定層疊佈局 Stack,教你怎麼讓元素像疊積木一樣玩出花來!全程只講能跑的代碼和避坑指南,保證看完就能用~ 🥦


什麼是層疊佈局?

層疊佈局(Stack Layout)就是在屏幕上劃一塊地方,讓裏面的元素能重疊顯示的佈局方式。想象一下你在桌上擺積木,後面放的積木會擋住前面的,Stack 佈局就是這個原理!

Stack 容器裏的子元素會按順序"入棧",後一個元素覆蓋前一個元素,就像這樣:

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_Stack

層疊佈局特別適合做廣告彈窗、卡片懸浮效果、底部導航欄等需要元素重疊的場景~

快速上手:第一個 Stack 佈局

説了這麼多,咱們直接上代碼!先整個最簡單的層疊佈局看看效果:

// StackExample.ets
let marginTop = { 'top': 50 } // 給個上邊距,讓內容不貼頂
@Entry
@Component
struct StackExample {
  build() {
    Column() {
      // 1. 創建Stack容器,默認子元素居中堆疊
      Stack({ }) {
        // 2. 第一層:綠色背景(最大)
        Column().width('90%').height('100%').backgroundColor('#ff58b87c')
        // 3. 第二層:淺粉色文本(中間)
        Text('我是中間層').width('60%').height('60%').backgroundColor('#ffc3f6aa')
        // 4. 第三層:淺藍色按鈕(最小)
        Button('點我呀').width('30%').height('30%').backgroundColor('#ff8ff3eb').fontColor('#000')
      }
      .width('100%').height(150).margin(marginTop)
    }
  }
}

運行效果長這樣:

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_嵌套_02

是不是超簡單?Stack 默認會把所有子元素居中堆疊,咱們只需要按順序放進去就行~


對齊方式:想咋疊就咋疊

默認居中當然不夠用,Stack 提供了 9 種對齊方式,讓你想咋疊就咋疊!

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_嵌套_03

咱們用alignContent參數來控制對齊方式,比如左上角對齊:

// StackAlignExample.ets
@Entry
@Component
struct StackAlignExample {
  build() {
    // 設置對齊方式為左上角
    Stack({ alignContent: Alignment.TopStart }) {
      Text('最底層').width('90%').height('100%').backgroundColor('#e1dede')
      Text('中間層').width('70%').height('80%').backgroundColor(0xd2cab3)
      Text('最上層').width('50%').height('60%').backgroundColor(0xc1cbac)
    }
    .width('100%').height(150).margin({ top: 5 })
  }
}

🥦 西蘭花小貼士: Alignment 的取值和 CSS 的 flex 佈局對齊方式很像,比如TopStart對應 CSS 的flex-startBottomEnd對應flex-end,用過 CSS 的朋友應該秒懂~ _


Z 序控制:誰在上面誰説了算

有時候咱們需要控制哪個元素在最上面,這時候就需要用到zIndex屬性了!zIndex值越大,元素層級越高,就會顯示在越上面~

先看個默認情況:

// StackZIndexExample1.ets
Stack({ alignContent: Alignment.BottomStart }) {
  Column() {
    Text('子元素1').textAlign(TextAlign.End).fontSize(20)
  }
  .width(100).height(100).backgroundColor(0xffd306) // 黃色

  Column() {
    Text('子元素2').fontSize(20)
  }
  .width(150).height(150).backgroundColor(Color.Pink) // 粉色

  Column() {
    Text('子元素3').fontSize(20)
  }
  .width(200).height(200).backgroundColor(Color.Grey) // 灰色
}
.width(350).height(350).backgroundColor(0xe0e0e0)

運行效果:

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_Text_04

因為子元素 3 是最後一個,而且尺寸最大,所以把前面兩個都擋住了!這時候咱們給前兩個元素加上zIndex

// StackZIndexExample2.ets
Stack({ alignContent: Alignment.BottomStart }) {
  Column() {
    Text('子元素1').fontSize(20)
  }
  .width(100).height(100).backgroundColor(0xffd306).zIndex(2) // 黃色,zIndex最高

  Column() {
    Text('子元素2').fontSize(20)
  }
  .width(150).height(150).backgroundColor(Color.Pink).zIndex(1) // 粉色,zIndex次之

  Column() {
    Text('子元素3').fontSize(20)
  }
  .width(200).height(200).backgroundColor(Color.Grey) // 灰色,默認zIndex最低
}
.width(350).height(350).backgroundColor(0xe0e0e0)

現在效果就變成這樣了:

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_Stack_05

是不是超直觀?zIndex 就像給元素髮了個"插隊卡",數值大的就能插前面~


實戰案例:仿手機桌面佈局

光説不練假把式,咱們整個實戰案例——仿手機桌面佈局,帶懸浮底部導航欄:

// StackHomeExample.ets
// 定義應用信息接口
interface AppInfo {
  name: string;
  color: string;
}

@Entry
@Component
struct StackHomeExample {
  // 模擬應用列表 - 每個應用都有自己的顏色
  private apps: AppInfo[] = [
    {name: '微信', color: '#07C160'},
    {name: '微博', color: '#E6162D'},
    {name: '抖音', color: '#FE2C55'},
    {name: 'B站', color: '#00A1D6'},
    {name: '淘寶', color: '#FF5000'},
    {name: '京東', color: '#E1251B'},
    {name: '支付寶', color: '#1677FF'},
    {name: '拼多多', color: '#FFD400'}
  ];

  build() {
    // 整個頁面作為Stack容器
    Stack({ alignContent: Alignment.Bottom }) {
      // 第一層:應用圖標網格
      Flex({ wrap: FlexWrap.Wrap }) {
        ForEach(this.apps, (app: AppInfo) => {
          Text(app.name)
            .width(100)
            .height(100)
            .fontSize(16)
            .fontColor(0xFFFFFF)
            .margin(10)
            .textAlign(TextAlign.Center)
            .borderRadius(10)
            .backgroundColor(app.color)
        }, (app: AppInfo): string => app.name)
      }
      .width('100%').height('100%')

      // 第二層:懸浮底部導航欄
      Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center }) {
        Text('聯繫人').fontSize(16)
        Text('設置').fontSize(16)
        Text('短信').fontSize(16)
      }
      .width('50%')
      .height(50)
      .backgroundColor('#16302e2e')
      .margin({ bottom: 15 })
      .borderRadius(15)
    }
    .width('100%').height('100%').backgroundColor('#CFD0CF')
  }
}

運行效果:

鴻蒙學習實戰之路-層疊佈局 Stack 全攻略_Text_06

這個案例是不是很實用?底部導航欄懸浮在應用圖標上方,用 Stack 佈局輕鬆實現~

🥦 西蘭花警告: 過多的嵌套 Stack 組件會導致性能問題哦!如果只是想實現簡單的元素疊加,比如給按鈕加個陰影,直接用組件的shadow屬性會比套個 Stack 性能更好~ 官方文檔裏也説了,能不用嵌套就不用,咱們要做個懂優化的好廚子!_


避坑指南

  1. 不要過度嵌套:Stack 嵌套超過 3 層,性能就會明顯下降,能用其他方式實現的效果儘量不用 Stack
  2. zIndex 的使用場景:只有當元素確實需要動態調整層級時才用 zIndex,否則儘量靠元素順序控制層級
  3. 對齊方式的選擇:根據實際需求選擇合適的對齊方式,避免用了BottomEnd又手動加margin去調整位置,多此一舉~

總結一下

今天咱們學會了:

  1. 層疊佈局 Stack:讓元素重疊顯示的佈局方式
  2. 對齊方式:用alignContent控制元素堆疊的位置
  3. Z 序控制:用zIndex控制元素的顯示層級
  4. 實戰案例:仿手機桌面佈局,帶懸浮底部導航欄

🥦 西蘭花小貼士: 官方文檔是個好東西!説三遍!關於 Stack 佈局的更多細節,可以去看看官方文檔~


👉 預告:《只會用基本佈局?鴻蒙還有這些高級佈局技巧!》

📚 推薦資料:

  • 官方層疊佈局文檔:層疊佈局 Stack
  • 組件嵌套優化指南:組件嵌套優化
  • 示例代碼倉庫:組件堆疊示例

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