HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之栅格布局

发布于 1周前 作者 yibo5220 来自 鸿蒙OS

HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之栅格布局

栅格布局(Grid Layout)在设计和开发领域中扮演着至关重要的角色,尤其是在响应式设计中。它是一种基于固定或可变单元格的布局系统,用于组织和对齐页面上的元素,使其在不同屏幕尺寸下都能保持一致性和美观性。

栅格布局的优势

  1. 规范性:通过固定的单元格,确保页面元素的一致性和可预测性。
  2. 响应式设计:栅格布局易于调整,可以适应不同设备和屏幕尺寸,实现响应式设计。
  3. 易读性和可用性:有序的布局使用户更容易理解和导航网站。
  4. 效率:对于开发者而言,使用栅格系统可以简化布局过程,减少编码工作量。

栅格布局的组成部分

  1. 容器(Container):定义了栅格的边界。
  2. (Row):横向分割容器,包含列。
  3. (Column):纵向分割行,用于放置内容。
  4. 间隔(Gutter):列与列之间的空白空间。
  5. 单元格(Cell):列的别称,表示栅格中的一个基本单位。
  6. 断点(Breakpoint):定义布局在不同屏幕尺寸下的变化点。

如上图:红色区域为列,列于列之间为间隔(Gutter)。

在鸿蒙系统中,栅格结合断点,实现栅格布局能力的组件叫栅格组件,需要使用GridRow和GridCol组件。

在实际使用场景中,可以根据需要配置不同断点下栅格组件中元素占据的列数,同时也可以调整Column和Gutter的值,从而实现不同的布局效果。

栅格布局 (GridRow/GridCol)

首先需要了解栅格布局中的断点,栅格系统默认断点将设备宽度分为xs、sm、md、lg四类,尺寸范围如下:

断点名称 取值范围(vp) 设备描述
xs [0, 320) 最小宽度类型设备。
sm [320, 520) 小宽度类型设备。
md [520, 840) 中等宽度类型设备。
lg [840, +∞) 大宽度类型设备。

在GridRow栅格组件中,开发者根据实际使用场景,通过一个数组,可以自定义最多六个断点。

breakpoints: {value: [‘100vp’, ‘200vp’]}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

表示启用xs、sm、md共3个断点,小于100vp为xs,100vp-200vp为sm,大于200vp为md。

鸿蒙系统中,栅格的默认列数12列,可以根据不同断点设置不同的列数(Column),设置不同的间隔(Gutter),设置栅格子组件占据的栅格容器列数。

  • GridRow的columns:设置不同断点的列数
  • GridRow的gutter: 设置子元素在水平和垂直方向的间距
  • GridColoffset:设置栅格子组件相对于前一个子组件的偏移列数,默认为0。
  • GridCol的span:设置子组件占栅格布局的列数,决定了子组件的宽度,默认为1。、

我们代码演示一下:

@Entry
@Component
struct TestDemo {
build() {
GridRow({
columns: {
sm: 4,  // 在小宽度类型设备上,列数为4
md: 8,  // 在中等类型设备上,列数为8
lg: 12  // 在大宽度度类型设备上,列数为12
},
gutter: {
x: {
sm: 12,  // 在小宽度类型设备上,水平方向间距12
md: 16,  // 在中等宽度类型设备上,水平方向间距16
lg: 24   // 在大宽度类型设备上,水平方向间距24
},
y: {
sm: 12, // 在小宽度类型设备上,垂直方向间距12
md: 16, // 在中等宽度类型设备上,垂直方向间距16
lg: 24  // 在大宽度类型设备上,垂直方向间距24
}
}
}) {

  <span class="hljs-comment"><span class="hljs-comment">// 重复多个</span></span>
  GridCol({
    span: {
      sm: <span class="hljs-number"><span class="hljs-number">2</span></span>, <span class="hljs-comment"><span class="hljs-comment">// 在小宽度类型设备上,栅格子组件占据的栅格容器2列。</span></span>
      md: <span class="hljs-number"><span class="hljs-number">2</span></span>, <span class="hljs-comment"><span class="hljs-comment">// 在中等宽度类型设备上,栅格子组件占据的栅格容器2列。</span></span>
      lg: <span class="hljs-number"><span class="hljs-number">2</span></span>  <span class="hljs-comment"><span class="hljs-comment">// 在大宽度类型设备上,栅格子组件占据的栅格容器2列。</span></span>
      }
    }) {
      Row(){}
      .width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
      .height(<span class="hljs-number"><span class="hljs-number">200</span></span>)
      .backgroundColor(Color.Orange)
  }
}

} }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

实现效果如下:

cke_268441.png

cke_271234.pngcke_275564.png

接下来我们进行一下实际业务场景的使用。在日常的业务场景中,经常会有列表信息的呈现,例如下面的商品列表:

cke_391854.png

在手机等小屏幕设备上为两列布局,如果在大屏上也是两列布局,就浪费了大屏的空间,体验会大打折扣。

为了在大屏和折叠屏上有更好的体验,我们需要根据断点结合栅格组件,实现不同屏幕下的列数和间距控制。

具体代码如下:

class ProductItem {
constructor(imageUrl: Resource, title: string) {
this.imageUrl = imageUrl;
this.title = title;
}
imageUrl: Resource
title: string
}

@Entry @Component struct ListDemo { @State currentBreakpoint: string = ‘unknown’; @State marginSize: number = 0 @State ListData: Array<ProductItem> = [ new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’), new ProductItem($r(‘app.media.p1’), ‘问界 新M7 Ultra’) ]

build() { // 配置不同断点下columns和gutter的取值 GridRow({ columns: { sm: 4, md: 8, lg: 12 }, gutter: { x: { sm: 12, md: 16, lg: 24}, y: { sm: 12, md: 16, lg: 24 } } }) { ForEach(this.ListData, (item: ProductItem)=>{ GridCol({span: {sm: 2, md: 2, lg: 2}}) { Column(){ Column() { Image(item.imageUrl).width(‘100%’).height(‘100%’) } .aspectRatio(1) .backgroundColor(’#E5E3E3’) .borderRadius(6) .clip(true)

        Text(item.title)
          .margin({ top: <span class="hljs-number"><span class="hljs-number">4</span></span> })
      }.margin({ bottom: <span class="hljs-number"><span class="hljs-number">10</span></span> })

    }
  })
}
.margin({left: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.marginSize, right: <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.marginSize})
.onBreakpointChange((currentBreakpoint: string) =&gt; {
  <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.currentBreakpoint = currentBreakpoint
  <span class="hljs-keyword"><span class="hljs-keyword">if</span></span> (currentBreakpoint === <span class="hljs-string"><span class="hljs-string">'lg'</span></span>) {
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.marginSize = <span class="hljs-number"><span class="hljs-number">24</span></span>
  }<span class="hljs-keyword"><span class="hljs-keyword">else</span></span> <span class="hljs-keyword"><span class="hljs-keyword">if</span></span>(currentBreakpoint === <span class="hljs-string"><span class="hljs-string">'md'</span></span>){
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.marginSize = <span class="hljs-number"><span class="hljs-number">16</span></span>
  } <span class="hljs-keyword"><span class="hljs-keyword">else</span></span> {
    <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.marginSize = <span class="hljs-number"><span class="hljs-number">12</span></span>
  }
})

} }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

通过对不同断点的列数和间距控制,同时在onBreakpointChange事件中动态修改marginLeft和marginRight的值,达到不同设备不同展示效果。

最新实现效果如下:

cke_696518.png

手机

cke_705396.png

折叠屏

cke_723137.png

平板

除了实现列表在不同设备上的布局,在实际业务中,也会遇到一个页面,需要在不同屏幕上保持尺寸的情况。

例如下面的登录页面:

手机

平板上不做适配

如图这样的页面,如果不做处理的话,在大屏上会进行延伸,导致页面变形。这种情况就需要结合GridRow和GridCol组件以及断点配置进行调整,使其在不同屏幕下都是居中显示,避免拉伸。

实现代码如下:

import router from ‘@ohos.router’;
@Entry
@Component
struct Login {
@State currentBreakpoint: string = ‘unknown’
@State name: string = ‘’
@State password: string = ‘’
build() {
GridRow({
columns: { sm: 4, md: 8, lg: 12 }
}) {
GridCol({
span:{
xs: 4,
sm: 4,
md: 6,
lg: 6,
xl: 6,
xxl: 6
},
offset: {
xs: 0,
sm: 0,
md: 1,
lg: 3,
xl: 3,
xxl: 3,
}
}) {
// 这里是登录的UI
}
}.onBreakpointChange((currentBreakpoint: string) => {
this.currentBreakpoint = currentBreakpoint
})
}
}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

最终实现效果:

手机

折叠屏折叠态

折叠屏展开态

平板

可以看到栅格组件结合断点设置,可以非常方便的优化不同屏幕上的交互体验。

HarmonyOS NEXT应用开发基础架构搭建-设计理念和目录结构

HarmonyOS NEXT应用开发基础架构搭建-模块设计

HarmonyOS NEXT应用开发基础架构搭建-路由管理

HarmonyOS NEXT应用开发基础架构搭建-路由页面权限控制

HarmonyOS NEXT应用开发基础架构搭建-多端布局之自适应布局

HarmonyOS NEXT应用开发基础架构搭建-多端布局之响应式布局

HarmonyOS NEXT应用开发基础架构搭建-多端布局之栅格布局



关于HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之栅格布局的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

2 回复
您好,栅格布局能设置滚动效果吗?

嵌套 list 试试

回到顶部