《鸿蒙HarmonyOS一多开发:自适应布局的设计与实践》

 注:适用版本(HarmonyOS NEXT/5.0/API12+)

  1. 背景与痛点分析

    • 多设备生态的挑战:手机、平板、车机、智能穿戴等不同屏幕尺寸和交互方式。

    • 传统开发的局限性:重复适配、代码冗余、维护成本高。

    • HarmonyOS的解决方案:"一次开发,多端部署"(一多开发)的核心优势。

  2. 自适应布局的核心概念

    • 原子化布局:基于组件化思想,拆解布局为可复用的最小单元。

    • 响应式设计:通过断点、栅格系统、比例缩放适配不同屏幕。

    • 多态控件:同一控件在不同设备上呈现不同交互形态(如手机上的列表 vs 手表上的卡片)。

    • 资源动态加载:根据设备类型加载不同的布局文件或样式。

  3. 实现自适应布局的关键步骤
    步骤1:明确设计原则

  4. 以内容为中心,优先保证核心功能一致性。

  5. 使用相对单位(vp/fp)而非固定像素,确保布局弹性。

  6. 遵循“最小差异”原则,减少多端适配的代码修改量。

实现自适应布局的关键步骤
步骤1:明确设计原则

  • 以内容为中心,优先保证核心功能一致性。

  • 使用相对单位(vp/fp)而非固定像素,确保布局弹性。

  • 遵循“最小差异”原则,减少多端适配的代码修改量。

步骤2:利用ArkUI布局能力

  • 弹性布局(Flex):通过Flex容器实现元素的自适应排列。

  • 网格布局(Grid):使用GridRow/GridCol构建响应式栅格系统。

  • 媒体查询(MediaQuery):监听屏幕属性(方向、分辨率)动态调整UI。

自适应布局的能力有 7 种,主要解决的是:窗口尺寸在【一定范围内】变化时,页面能够正常显示

自适应布局能力

使用场景

实现方式

拉伸能力

容器组件尺寸发生变化时,增加或减小的空间全部分配给容器组件内指定区域

Flex布局

的flexGrow和flexShrink属性

均分能力

容器组件尺寸发生变化时,增加或减小的空间均匀分配给容器组件内所有空白区域

Row组件

、Column组件

或Flex组件

的justifyContent属性设置为FlexAlign.SpaceEvenly

占比能力

子组件的宽或高按照预设的比例,随容器组件发生变化。

基于通用属性的两种实现方式:
- 将子组件的宽高设置为父组件宽高的百分比
- layoutWeight属性

缩放能力

子组件的宽高按照预设的比例,随容器组件发生变化,且变化过程中子组件的宽高比不变

布局约束

的aspectRatio属性

延伸能力

容器组件内的子组件,按照其在列表中的先后顺序,随容器组件尺寸变化显示或隐藏。

基于容器组件的两种实现方式:
- 通过List组件

实现
- 通过Scroll组件

配合Row组件

或Column组件

实现

隐藏能力

容器组件内的子组件,按照其预设的显示优先级,随容器组件尺寸变化显示或隐藏。相同显示优先级的子组件同时显示或隐藏

布局约束

的displayPriority属性

折行能力

容器组件尺寸发生变化时,如果布局方向尺寸不足以显示完整内容,自动换行

Flex组件

的wrap属性设置为FlexWrap.Wrap

 拉伸能力指的是容器尺寸发生变化时:将变化的空间,分配给容器内的【指定区域】。利用的是 2 个属性:

测试代码

@Entry
@Component
struct Demo01 {
  // 绑定的宽度-默认 600
  @State containerWidth: number = 600

  // 底部滑块,可以通过拖拽滑块改变容器尺寸。
  @Builder
  sliderBuilder() {
    Slider({
      value: this.containerWidth, // 绑定的值
      min: 400, // 最小值
      max: 1000, // 最大值
      style: SliderStyle.OutSet // 滑块在滑轨上
    })
      .blockColor(Color.White)
      .width('60%')
      .position({ x: '20%', y: '80%' })
      .onChange((value)=>{
        this.containerWidth = value
      })
  }

  build() {
    Stack({ alignContent: Alignment.TopStart }) {
      // 标记现在的宽度
      Text('宽度:' + this.containerWidth)
        .zIndex(2)
        .translate({ x: 20, y: 20 })
        .fontColor(Color.Orange)

      // 核心区域
      Column() {
        Column() {
          Row() {
            // 左
            Row() {
              Text('左')
                .fontSize(20)
                .fontColor(Color.White)
            }
            .justifyContent(FlexAlign.Center)
            .width(150)
            .height(290)
            .backgroundColor('#c2baa6')
            .flexShrink(1)

            // 中
            Row() {
              Text('中')
                .fontSize(30)
                .fontColor(Color.White)
            }
            .width(300)
            .height(290)
            .backgroundColor('#68a67d')
            .justifyContent(FlexAlign.Center)
            .flexGrow(1)


            // 右
            Row() {
              Text('右')
                .fontSize(20)
                .fontColor(Color.White)
            }
            .justifyContent(FlexAlign.Center)
            .width(150)
            .height(290)
            .backgroundColor('#c2baa6')
            .flexShrink(1)

          }
          .width(this.containerWidth)
          .justifyContent(FlexAlign.Center)
          .alignItems(VerticalAlign.Center)
          .border({ width: 2, color: Color.Orange })
          .backgroundColor(Color.Black)
        }

        // 底部滑块
        this.sliderBuilder()
      }
      .width('100%')
      .height('100%')
      .backgroundColor(Color.Pink)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
      .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
    }
  }
}

按照这个模板我们可以按照图标进行其他的能力测试

总结:

拉伸能力:flexGrow和flexShrink属性

均分能力:FLexALign.SpaceEvenly属性

占比能力:子组件宽高占比、layoutWeight

缩放能力:aspectRatio属性

延伸能力:List组件、Scroll组件

隐藏能力:displayPriority属性

折行能力:FLex组件,wrap属性、FLexWrap.Wrap

你可能感兴趣的:(harmonyos,华为,一多开发,鸿蒙)