鴻蒙HarmonyOS NEXT開(kāi)發(fā):自適應(yīng)布局的介紹,使用場(chǎng)景、實(shí)現(xiàn)方式與示例解析

一、布局簡(jiǎn)介

自適應(yīng)布局是通過(guò)設(shè)定元素與外部容器的相對(duì)關(guān)系實(shí)現(xiàn)的。當(dāng)外部容器大小、位置等發(fā)生變化時(shí),元素即可以根據(jù)相對(duì)關(guān)系自動(dòng)變化以適應(yīng)外部環(huán)境的變化。通常自適應(yīng)布局能根據(jù)vp/px變化進(jìn)行無(wú)級(jí)連續(xù)的變化。

  • 自適應(yīng)布局常常需要借助Row組件、Column組件或Flex組件實(shí)現(xiàn)。
微信圖片_20250108144026.png
  • 針對(duì)常見(jiàn)的開(kāi)發(fā)場(chǎng)景,方舟開(kāi)發(fā)框架提煉了七種自適應(yīng)布局能力,這些布局可以獨(dú)立使用,也可多種布局疊加使用。
自適應(yīng)布局能力 使用場(chǎng)景 實(shí)現(xiàn)方式
拉伸能力 容器組件尺寸發(fā)生變化時(shí),增加或減小的空間全部分配給容器組件內(nèi)指定區(qū)域。 Flex布局的flexGrow和flexShrink屬性
均分能力 容器組件尺寸發(fā)生變化時(shí),增加或減小的空間均勻分配給容器組件內(nèi)所有空白區(qū)域。 Row組件、Column組件或Flex組件的justifyContent屬性設(shè)置為FlexAlign.SpaceEvenly
占比能力 子組件的寬或高按照預(yù)設(shè)的比例,隨容器組件發(fā)生變化。 基于通用屬性的兩種實(shí)現(xiàn)方式:
將子組件的寬高設(shè)置為父組件寬高的百分比
layoutWeight屬性
縮放能力 子組件的寬高按照預(yù)設(shè)的比例,隨容器組件發(fā)生變化,且變化過(guò)程中子組件的寬高比不變。 布局約束的aspectRatio屬性
延伸能力 容器組件內(nèi)的子組件,按照其在列表中的先后順序,隨容器組件尺寸變化顯示或隱藏。 基于容器組件的兩種實(shí)現(xiàn)方式:
通過(guò)List組件實(shí)現(xiàn)
通過(guò)Scroll組件配合Row組件或Column組件實(shí)現(xiàn)
隱藏能力 容器組件內(nèi)的子組件,按照其預(yù)設(shè)的顯示優(yōu)先級(jí),隨容器組件尺寸變化顯示或隱藏。相同顯示優(yōu)先級(jí)的子組件同時(shí)顯示或隱藏。 布局約束的displayPriority屬性
折行能力 容器組件尺寸發(fā)生變化時(shí),如果布局方向尺寸不足以顯示完整內(nèi)容,自動(dòng)換行。 Flex組件的wrap屬性設(shè)置為FlexWrap.Wrap

二、自適應(yīng)拉伸

某單個(gè)內(nèi)容或某組內(nèi)容的顯示寬度不是固定值,而是通過(guò)相對(duì)參照物的方式來(lái)確定其顯示寬度。當(dāng)參照物的寬度發(fā)生變化時(shí),內(nèi)容或內(nèi)容間距的寬度隨之發(fā)生自適應(yīng)拉伸。

自適應(yīng)拉伸適用于文字、普通按鈕、間距等展示寬度靈活,對(duì)寬高比不敏感的內(nèi)容和內(nèi)容組合。

當(dāng)可能出現(xiàn)的拉伸寬度不足以顯示默認(rèn)內(nèi)容時(shí),應(yīng)根據(jù)場(chǎng)景選擇優(yōu)先保證內(nèi)容完整或者優(yōu)先保證其他內(nèi)容的屏效,并進(jìn)行截?cái)嗷驌Q行等組合適配。

1、左右拉伸

例如,列表開(kāi)關(guān)組合中,在窗口寬度變化時(shí),開(kāi)關(guān)控件固定寬度并相對(duì)列表的右邊緣位置固定,整個(gè)組合與文本寬度均自適應(yīng)變化。


拉伸能力.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  build() {
    Column() {
      Row() {
        Text('健康使用手機(jī)')
          .fontSize(16)
          .height(22)
          .fontWeight(FontWeight.Medium)
          .lineHeight(22)
        Blank() // 通過(guò)Blank組件實(shí)現(xiàn)拉伸能力
        Toggle({ type: ToggleType.Switch })
          .width(36)
          .height(20)
      }
      .height(55)
      .borderRadius(12)
      .padding({ left: 15, right: 15 })
      .backgroundColor('#FFFFFF')
      .width('100%')//此處寬度變化時(shí),文字和開(kāi)關(guān)的尺寸固定,僅有中間空白區(qū)域(Blank組件)隨父容器尺寸變化而伸縮。
    }
    .height('100%')
    .width('100%')
    .padding(20)
    .backgroundColor(Color.Gray)
  }
}

2、均分拉伸

例如,在圖標(biāo)型網(wǎng)格中,當(dāng)窗口寬度變化時(shí),入口圖標(biāo)間距與圖標(biāo)離左右邊緣間距同時(shí)均等變化。

均分能力.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  readonly list: number [] = [0, 1, 2, 3]

  build() {
    Column() {
      // 均勻分配父容器主軸方向的剩余空間
      Row() {
        ForEach(this.list, (item: number) => {
          Column() {
            Image($r("app.media.startIcon"))
              .width(48)
              .height(48)
              .margin({ top: 8 })
            Text('App name')
              .width(64)
              .height(30)
              .lineHeight(15)
              .fontSize(12)
              .textAlign(TextAlign.Center)
              .margin({ top: 8 })
              .padding({ bottom: 15 })
          }
          .width(80)
          .height(102)
          .flexShrink(1)
        })
      }
      .width('100%')//寬度變化時(shí),圖標(biāo)及文字的尺寸不變,圖標(biāo)間的間距及圖標(biāo)離左右邊緣的距離同時(shí)均等改變。
      .justifyContent(FlexAlign.SpaceEvenly)
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.White)
  }
}

三、自適應(yīng)縮放

組件的顯示大小是固定比例,通過(guò)相對(duì)參照物的方式來(lái)確定其寬或高。當(dāng)參照物的大小發(fā)生變化時(shí),元素的大小隨之發(fā)生自適應(yīng)縮放。

自適應(yīng)縮放適用于圖片、圓形按鈕、banner、反應(yīng)真實(shí)物體形狀的圖像等必須保證寬高比的內(nèi)容。

不推薦將所有元素同時(shí)縮放、或某內(nèi)容放大過(guò)大超過(guò)屏幕50%。這將導(dǎo)致獲取信息量不增反減,不符合用戶預(yù)期。

1、完整縮放

例如,在寬度或高度變化時(shí),時(shí)鐘始終保證表盤(pán)完整展示并根據(jù)較短邊決定寬高。

zh-cn_image_0000001568293145.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  build() {
    Column() {
      Column() {
        Column() {
          Image($r("app.media.1"))
            .width('100%')
            .height('100%')
        }
        .aspectRatio(1)// 固定寬高比
      }
      .backgroundColor(Color.Pink)
      .height(200)//這里寬或高改變是,圖片也隨之變化
      .width(400)//這里寬或高改變是,圖片也隨之變化
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.White)
  }
}

2、占比縮放

例如,帶主體和背景的插畫(huà),畫(huà)面內(nèi)容根據(jù)寬度變化裁切,根據(jù)高度變化按50%比例縮放。


縮放案例.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  build() {
    Column() {
      Row(){

      }
      .backgroundImage($r('app.media.banner'))
      .backgroundImageSize(ImageSize.Cover)
      .width('100%')
      .layoutWeight(1)

      Row(){

      }
      .backgroundColor(Color.White)
      .width('100%')
      .layoutWeight(1)
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Gray)
  }
}

四、自適應(yīng)延伸

組件的顯示數(shù)量不是固定的,而是通過(guò)相對(duì)參照物的方式來(lái)確定其顯示數(shù)量。當(dāng)參照物的寬度發(fā)生變化時(shí),組件隨之發(fā)生自適應(yīng)延伸顯示更多數(shù)量。

自適應(yīng)延伸/隱藏適用于頁(yè)簽、操作塊、推薦欄目等具有相同交互層級(jí)且有更多數(shù)據(jù)可以填充的內(nèi)容。

注意:需要判斷因隱藏而不展示的內(nèi)容對(duì)功能完整性是否有影響,并考慮通過(guò)滑動(dòng)或“更多”按鈕提供查看使用該內(nèi)容的方式。

1、同功能內(nèi)容延伸

例如,子頁(yè)簽和可滑動(dòng)宮格在默認(rèn)寬度下通過(guò)露出最后內(nèi)容,提示右方有更多入口,在寬度變化時(shí),可在每個(gè)元素寬度不變、保持滑動(dòng)交互時(shí)顯示更多數(shù)量。

延長(zhǎng)能力.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  readonly appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7]
  build() {
    Column() {
      Row({ space: 10 }) {
        // 通過(guò)List組件實(shí)現(xiàn)隱藏能力
        List({ space: 10 }) {
          ForEach(this.appList, (item:number) => {
            ListItem() {
              Column() {
                Image($r("app.media.startIcon"))
                  .width(48)
                  .height(48)
                  .margin({ top: 8 })
                Text('App name')
                  .width(64)
                  .height(30)
                  .lineHeight(15)
                  .fontSize(12)
                  .textAlign(TextAlign.Center)
                  .margin({ top: 8 })
                  .padding({ bottom: 15 })
              }.width(80).height(102)
            }.width(80).height(102)
          })
        }
        .padding({ top: 16, left: 10 })
        .listDirection(Axis.Horizontal)
        .width('100%')
        .height(118)
        .borderRadius(16)
        .backgroundColor(Color.White)
      }
      .width('100%')//這里寬度變化,頁(yè)面中顯示的圖標(biāo)數(shù)量隨之發(fā)生改變。
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Gray)
  }
}

2、不同功能內(nèi)容延伸或隱藏

例如,默認(rèn)處于同一排的不同音樂(lè)播放按鈕優(yōu)先級(jí)不同,在寬度變化時(shí)可延伸或隱藏低優(yōu)先級(jí)的按鈕,最大化適應(yīng)不同窗口尺寸。

隱藏能力.gif

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  build() {
    Column() {
      Row({ space:24 }) {
        Image($r("sys.media.ohos_ic_public_sound_off"))
          .width(48)
          .height(48)
          .objectFit(ImageFit.Contain)
          .displayPriority(1)  // 布局優(yōu)先級(jí)

        Image($r("sys.media.ohos_ic_public_play_last"))
          .width(48)
          .height(48)
          .objectFit(ImageFit.Contain)
          .displayPriority(2)  // 布局優(yōu)先級(jí)

        Image($r("sys.media.ohos_ic_public_pause"))
          .width(48)
          .height(48)
          .objectFit(ImageFit.Contain)
          .displayPriority(3)  // 布局優(yōu)先級(jí)

        Image($r("sys.media.ohos_ic_public_play_next"))
          .width(48)
          .height(48)
          .objectFit(ImageFit.Contain)
          .displayPriority(2)  // 布局優(yōu)先級(jí)

        Image($r("sys.media.ohos_ic_public_more"))
          .width(48)
          .height(48)
          .objectFit(ImageFit.Contain)
          .displayPriority(1)  // 布局優(yōu)先級(jí)
      }
      .width('100%')//父容器寬度發(fā)生變化時(shí),其子元素按照預(yù)設(shè)的優(yōu)先級(jí)顯示或隱藏。
      .height(96)
      .borderRadius(16)
      .backgroundColor('#FFFFFF')
      .justifyContent(FlexAlign.Center)
      .alignItems(VerticalAlign.Center)
    }
    .height('100%')
    .width('100%')
    .padding(10)
    .backgroundColor(Color.Gray)
  }
}

五、自適應(yīng)折行

定義了折行能力的組件,可以根據(jù)組件容器的可用空間,體現(xiàn)縱向布局或者橫向布局。

自適應(yīng)折行適用于頁(yè)簽、操作塊、內(nèi)容流等具有相同交互層級(jí),且希望保證類型和數(shù)量完整性的內(nèi)容。

自適應(yīng)布局對(duì)應(yīng)OpenHarmony系統(tǒng)提供的自適應(yīng)布局能力中的拉伸、均分、縮放、占比、延伸、隱藏、折行。

例如,在寬度足夠時(shí),操作塊位于同一行,在寬度變小時(shí),可根據(jù)內(nèi)容能顯示的寬度縱向排布。

折行案例分鏡.png

示例代碼

@Entry
@Component
struct AdaptiveLayoutPage {
  readonly searchList: string [] = ['搖滾', '九十年代金曲', '交響樂(lè)', '流行']

  build() {
    Column() {
      // 通過(guò)Flex組件warp參數(shù)實(shí)現(xiàn)自適應(yīng)折行
      Flex({
        direction: FlexDirection.Row,
        alignItems: ItemAlign.Center,
        justifyContent: FlexAlign.Start,
        wrap: FlexWrap.Wrap
      }) {
        ForEach(this.searchList, (item: Resource) => {
          Text(item)
            .padding({
              top: 8,
              bottom: 8,
              left: 20,
              right: 20
            })
            .margin(8)
            .fontSize(16)
            .fontWeight(500)
            .borderRadius('50%')
            .backgroundColor('#e1e3e5')
        })
      }
      .backgroundColor('#FFFFFF')
      .padding(10)
      .width('100%')//當(dāng)父容器寬度發(fā)生變化,其中的內(nèi)容做自適應(yīng)換行。
      .borderRadius(15)
    }
    .height('100%')
    .width('100%')
    .padding(10)
    .backgroundColor(Color.Gray)
  }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容