鴻蒙HarmonyOS NEXT開發:一次開發,多端部署(界面級)常見布局解決方案

雖然不同應用的頁面千變萬化,但對其進行拆分和分析,頁面中的很多布局場景是相似的。本小節將介紹如何借助自適應布局、響應式布局以及常見的容器類組件,實現應用中的典型布局場景。

1、頂部單張大圖

頂部背景圖被拉伸時,可以通過設置背景圖片的backgroundImageSize屬性,使得圖片大小能夠合理顯示,達到適配效果。

微信圖片_20250109103301.png

參考代碼

@Entry
@Component
struct FQPage {

  build() {
    Column() {
      // 設置背景圖片的backgroundImageSize屬性,使得圖片大小能夠合理顯示
      Column()
        .width('100%')
        .height(300)
        .backgroundColor('#ccc')
        .backgroundImage($r('app.media.1'))
        .backgroundImageSize(ImageSize.Cover)
        .backgroundImagePosition(Alignment.Center)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

2、網格列表

在大屏上,Listitem內容會過大,頁面整體瀏覽內容減少。可通過以下兩種方法解決:

微信圖片_20250109103202.png
  • 設置List列的最小寬度和最大寬度,使List組件根據寬度自適應決定列數。
  • 借助柵格行組件GridRow,調整不同的斷點下List組件的寬度。
@Entry
@Component
struct FQPage {
  @State data: Resource[] = new Array(5).fill($r("app.media.1"))
  @State breakPoint: string = 'sm'

  build() {
    GridRow() {
      GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
        List({ space: 24 }) {
          ForEach(this.data, (item: Resource) => {
            ListItem() {
              Image(item).margin({ left: 12, right: 12 })
            }
          })
        }
        // 設置列最小寬度和最大寬度
        .lanes({ minLength: 300, maxLength: 360 }).padding(12)
      }
    }.onBreakpointChange((breakpoint: string) => {
      this.breakPoint = breakpoint
    })
  }
}
  • 根據斷點設置List列數。
@Entry
@Component
struct FQPage {
  @State data: Resource[] = new Array(5).fill($r("app.media.1"))
  @State breakPoint: string = 'sm'

  build() {
    GridRow() {
      GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
        List({ space: 24 }) {
          ForEach(this.data, (item: Resource) => {
            ListItem() {
              Image(item).margin({ left: 12, right: 12 })
            }
          })
        }
        // 根據斷點設置List列數
        .lanes(this.breakPoint === 'sm' ? 1 : this.breakPoint === 'md' ? 2 : 3)
        .padding(12)
      }
    }.onBreakpointChange((breakpoint: string) => {
      this.breakPoint = breakpoint
    })
  }
}

3、運營橫幅(Banner)

在大屏上,Swiper圖片顯示內容過大,可以通過增加Swiper展示圖片數來調整圖片顯示大小。外層可以使用柵格組件GridRow,通過調用OnBreakpointChange事件,調整不同的斷點下Swiper的前后邊距,實現在不同屏幕尺寸上的顯示不同Swiper圖片數。

不同斷點下,運營橫幅中展示的圖片數量不同。只需要結合響應式布局,配置不同斷點下Swiper組件的displayCount屬性,即可實現目標效果。

微信圖片_20250109103125.png
@Entry
@Component
struct FQPage {

  @State data: Resource[] = new Array(6).fill($r("app.media.1"))
  @State breakPoint: string = 'sm'

  build() {
    Column() {
      Row() {
        GridRow() {
          GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
            Swiper() {
              ForEach(this.data, (item: Resource) => {
                Image(item)
                  .width('100%')
                  .height(200)
                  .objectFit(ImageFit.Cover)
              })
            }
            // 根據斷點設置Swiper圖片數量
            .displayCount(this.breakPoint === 'lg' ? 2 : 1, true)
            .autoPlay(true)
            .loop(true)
            .width('100%')
            .itemSpace(24)
            // 根據斷點設置Swiper前后邊距
            .prevMargin(this.breakPoint === 'md' ? 150 : 0)
            .nextMargin(this.breakPoint === 'md' ? 150 : 0)
          }
        }.onBreakpointChange((breakpoint: string) => {
          this.breakPoint = breakpoint
        })
      }
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

4、信息流單張圖片

針對信息流單張圖片過大的情況,設置aspectRatio和constrainSize屬性,可以通過對圖片的布局和尺寸進行約束,達到適配效果。

微信圖片_20250109103044.png
@Entry
@Component
struct FQPage {
  @State breakPoint: string = 'sm'

  build() {
    Column() {
      GridRow(){
        GridCol({ span: { sm: 12, md: 12, lg: 12 } }){
          Column(){
            Text('一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。')
            // 設置aspectRatio和constrainSize屬性,可以對圖片的布局和尺寸進行約束
            Image($r('app.media.1'))
              .width('50%')
              .aspectRatio(1)
              .constraintSize({ maxWidth: 320, minWidth: 180 })
            Text('一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。')
          }.alignItems(HorizontalAlign.Start)

        }
      }.onBreakpointChange((breakpoint: string) => {
        this.breakPoint = breakpoint
      })
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

5、信息流4宮格圖片

在大屏上,Grid組件里的4宮格圖片大小過大,頁面瀏覽區域變少。可以借助柵格行組件GridRow來調整不同的斷點下Grid的寬度,解決大屏上Grid組件4宮格圖片過大的問題。

微信圖片_20250109102910.png
@Entry
@Component
struct FQPage {
  @State data: Resource[] = new Array(4).fill($r("app.media.1"))
  @State breakPoint: string = 'sm'

  build() {
    Column() {
      GridRow() {
        GridCol({ span: { sm: 12, md: 12, lg: 12 } }) {
          Column({ space: 10 }) {
            Text('一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。在大屏上,Grid組件里的4宮格圖片大小過大,頁面瀏覽區域變少。可以借助柵格行組件GridRow來調整不同的斷點下Grid的寬度,解決大屏上Grid組件4宮格圖片過大的問題。')
              .lineHeight(24)
              .fontSize(15)
            Grid() {
              ForEach(this.data, (item: Resource) => {
                GridItem() {
                  Image(item)
                    .width('100%')
                    .aspectRatio(1)
                }
              })
            }.columnsTemplate('1fr 1fr')
            .columnsGap(10)
            .rowsGap(10)
            // 根據斷點設置Grid寬度
            .width(this.breakPoint === 'sm' ? '100%' : this.breakPoint === 'md' ? '60%' : '40%')
          }.width('100%')
          .alignItems(HorizontalAlign.Start)
        }
      }.onBreakpointChange((breakpoint: string) => {
        this.breakPoint = breakpoint
      })
    }
    .height('100%')
    .width('100%')
    .padding(10)
    .backgroundColor('#F1F3F5')
  }
}

6、信息流9宮格圖片

在大屏上,Grid組件里的9宮格圖片大小過大,頁面整體瀏覽內容減少,可以設置Grid組件寬度和寬高比,使Grid組件保持固定大小,不會隨著屏幕尺寸變化而變化。

微信圖片_20250109102948.png
@Entry
@Component
struct FQPage {
  @State data: Resource[] = new Array(9).fill($r("app.media.1"))

  build() {
    Column() {
      Column({ space: 10 }) {
        Text('一次開發,多端部署,讓開發者可以基于一種設計,高效構建多端可運行的應用。在大屏上,Grid組件里的9宮格圖片大小過大,頁面整體瀏覽內容減少,可以設置Grid組件寬度和寬高比,使Grid組件保持固定大小,不會隨著屏幕尺寸變化而變化。')
          .lineHeight(24)
          .fontSize(15)
        Grid() {
          ForEach(this.data, (item: Resource) => {
            GridItem() {
              Image(item)
                .width('100%')
                .aspectRatio(1)
            }
          })
        }
        .columnsTemplate('1fr 1fr 1fr')
        .columnsGap(10)
        .rowsGap(10)
        // 設置固定寬度和寬高比
        .width(360)
        .aspectRatio(1)
      }.width('100%')
      .alignItems(HorizontalAlign.Start)
    }
    .height('100%')
    .width('100%')
    .padding(10)
    .backgroundColor('#F1F3F5')
  }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容