Skip to content

相对布局

知识点

  1. RelativeContainer 为采用相对布局的容器,支持容器内部的子元素设置相对位置关系,适用于界面复杂场景的情况,对多个子组件进行对齐和排列。

  2. id 或者 __container__ 作为锚点,基于锚点做相对位置布局。

  3. 利用 offset 偏移

  4. 利用 alignRules 绑定

子元素并不完全是上图中的依赖关系。比如,Item4 可以以 Item2 为依赖锚点,也可以以 RelativeContainer 父容器为依赖锚点。

知识点概括

注意

  1. 子组件需要定位, RelativeContainer 必须是父容器.

  2. alignRules 里面必须有上下,左右其中两个定位

  3. 设定 alignRules 里面必须有两个参数,一个是 anchor(锚点),一个是 align(规则)

基本概念

  • 锚点: 通过锚点设置当前元素基于哪个元素确定位置。

  • 对齐方式:通过对齐方式,设置当前元素是基于锚点的上中下对齐,还是基于锚点的左中右对齐。

设置依赖关系

  • 锚点设置是指设置子元素相对于父元素或兄弟元素的位置依赖关系。在水平方向上,可以设置 left、middle、right 的锚点。在竖直方向上,可以设置 top、center、bottom 的锚点。

  • 子元素必须设置锚点 ID,如果不设置 id 的组件能显示,但是不能被其他子组件作为锚点

  • 通过 alignRules 绑定

代码

  • RelativeContainer父组件为锚点,__container__代表父容器的 ID。
ts
let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
  'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start }
}
let AlignRue: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
  'right': { 'anchor': '__container__', 'align': HorizontalAlign.End }
}
let Mleft: Record<string, number> = { 'left': 20 }
let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' }

@Entry
@Component
struct Index {
  build() {
    RelativeContainer() {
      Row() {
        Text('row1')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#a3cf62')
      .alignRules(AlignRus)
      .id("row1")

      Row() {
        Text('row2')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#00ae9d')
      .alignRules(AlignRue)
      .id("row2")
    }.width(300).height(300)
    .margin(Mleft)
    .border(BWC)
  }
}
  • 以兄弟元素作为锚点
ts
let AlignRus: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'top': { 'anchor': '__container__', 'align': VerticalAlign.Top },
  'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start }
}
let RelConB: Record<string, Record<string, string | VerticalAlign | HorizontalAlign>> = {
  'top': { 'anchor': 'row1', 'align': VerticalAlign.Bottom },
  'left': { 'anchor': 'row1', 'align': HorizontalAlign.Start }
}
let Mleft: Record<string, number> = { 'left': 20 }
let BWC: Record<string, number | string> = { 'width': 2, 'color': '#6699FF' }

@Entry
@Component
struct Index {
  build() {
    RelativeContainer() {
      Row() {
        Text('row1')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#00ae9d')
      .alignRules(AlignRus)
      .id("row1")

      Row() {
        Text('row2')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#a3cf62')
      .alignRules(RelConB)
      .id("row2")
    }.width(300).height(300)
    .margin(Mleft)
    .border(BWC)
  }
}
  • 子组件锚点可以任意选择,但注意不要相互依赖
ts
@Entry
@Component
struct Index {
  build() {
    Row() {
      RelativeContainer() {
        Row(){Text('row1')}.justifyContent(FlexAlign.Center).width(100).height(100)
        .backgroundColor('#a3cf62')
        .alignRules({
          top: {anchor: "__container__", align: VerticalAlign.Top},
          left: {anchor: "__container__", align: HorizontalAlign.Start}
        })
        .id("row1")

        Row(){Text('row2')}.justifyContent(FlexAlign.Center).width(100)
        .backgroundColor('#00ae9d')
        .alignRules({
          top: {anchor: "__container__", align: VerticalAlign.Top},
          right: {anchor: "__container__", align: HorizontalAlign.End},
          bottom: {anchor: "row1", align: VerticalAlign.Center},
        })
        .id("row2")

        Row(){Text('row3')}.justifyContent(FlexAlign.Center).height(100)
        .backgroundColor('#0a59f7')
        .alignRules({
          top: {anchor: "row1", align: VerticalAlign.Bottom},
          left: {anchor: "row1", align: HorizontalAlign.Start},
          right: {anchor: "row2", align: HorizontalAlign.Start}
        })
        .id("row3")

        Row(){Text('row4')}.justifyContent(FlexAlign.Center)
        .backgroundColor('#2ca9e0')
        .alignRules({
          top: {anchor: "row3", align: VerticalAlign.Bottom},
          left: {anchor: "row1", align: HorizontalAlign.Center},
          right: {anchor: "row2", align: HorizontalAlign.End},
          bottom: {anchor: "__container__", align: VerticalAlign.Bottom}
        })
        .id("row4")
      }
      .width(300).height(300)
      .margin({left: 50})
      .border({width:2, color: "#6699FF"})
    }
    .height('100%')
  }
}

设置锚点相对于锚点的对齐位置

设置了锚点之后,可以通过 align 设置相对于锚点的对齐位置。

  • 在水平方向上,对齐位置可以设置为 HorizontalAlign.StartHorizontalAlign.CenterHorizontalAlign.End
  • 在竖直方向上,对齐位置可以设置为 VerticalAlign.TopVerticalAlign.CenterVerticalAlign.Bottom

子组件位置偏移

子组件经过相对位置对齐后,位置可能还不是目标位置,开发者可根据需要进行额外偏移设置 offset

ts
@Entry
@Component
struct Index {
build() {
  Row() {
    RelativeContainer() {
      Row() {
        Text('row1')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#a3cf62')
      .alignRules({
        top: { anchor: "__container__", align: VerticalAlign.Top },
        left: { anchor: "__container__", align: HorizontalAlign.Start }
      })
      .id("row1")

      Row() {
        Text('row2')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .backgroundColor('#00ae9d')
      .alignRules({
        top: { anchor: "__container__", align: VerticalAlign.Top },
        right: { anchor: "__container__", align: HorizontalAlign.End },
        bottom: { anchor: "row1", align: VerticalAlign.Center },
      })
      .offset({
        x: -40,
        y: -20
      })
      .id("row2")

      Row() {
        Text('row3')
      }
      .justifyContent(FlexAlign.Center)
      .height(100)
      .backgroundColor('#0a59f7')
      .alignRules({
        top: { anchor: "row1", align: VerticalAlign.Bottom },
        left: { anchor: "row1", align: HorizontalAlign.End },
        right: { anchor: "row2", align: HorizontalAlign.Start }
      })
      .offset({
        x: -10,
        y: -20
      })
      .id("row3")

      Row() {
        Text('row4')
      }
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#2ca9e0')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
        left: { anchor: "__container__", align: HorizontalAlign.Start },
        right: { anchor: "row1", align: HorizontalAlign.End }
      })
      .offset({
        x: -10,
        y: -30
      })
      .id("row4")

      Row() {
        Text('row5')
      }
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#30c9f7')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
        left: { anchor: "row2", align: HorizontalAlign.Start },
        right: { anchor: "row2", align: HorizontalAlign.End }
      })
      .offset({
        x: 10,
        y: 20
      })
      .id("row5")

      Row() {
        Text('row6')
      }
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#ff33ffb5')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "row4", align: VerticalAlign.Bottom },
        left: { anchor: "row3", align: HorizontalAlign.Start },
        right: { anchor: "row3", align: HorizontalAlign.End }
      })
      .offset({
        x: -15,
        y: 10
      })
      .backgroundImagePosition(Alignment.Bottom)
      .backgroundImageSize(ImageSize.Cover)
      .id("row6")
    }
    .width(300).height(300)
    .margin({ left: 50 })
    .border({ width: 2, color: "#6699FF" })
  }
  .height('100%')
}
}

特别注意

注意

  1. 子组件尺寸大小不会受到相对布局的影响.

  2. 若子组件某个方向上设置两个或以上 alignRules 时最好不设置此方向尺寸大小,否则对齐规则确定的组件尺寸与开发者设置的尺寸可能产生冲突。

  3. 简单来说 设置了 top 就不要设置 bottom 设置 left 就不要设置 right

  • 代码如下
ts
@Entry
@Component
struct Index {
build() {
  Row() {
    RelativeContainer() {
      Row() {
        Text('row1')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .height(100)
      .backgroundColor('#a3cf62')
      .alignRules({
        top: { anchor: "__container__", align: VerticalAlign.Top },
        left: { anchor: "__container__", align: HorizontalAlign.Start }
      })
      .id("row1")

      Row() {
        Text('row2')
      }
      .justifyContent(FlexAlign.Center)
      .width(100)
      .backgroundColor('#00ae9d')
      .alignRules({
        top: { anchor: "__container__", align: VerticalAlign.Top },
        right: { anchor: "__container__", align: HorizontalAlign.End },
        bottom: { anchor: "row1", align: VerticalAlign.Center },
      })
      .id("row2")

      Row() {
        Text('row3')
      }
      .justifyContent(FlexAlign.Center)
      .height(100)
      .backgroundColor('#0a59f7')
      .alignRules({
        top: { anchor: "row1", align: VerticalAlign.Bottom },
        left: { anchor: "row1", align: HorizontalAlign.End },
        right: { anchor: "row2", align: HorizontalAlign.Start }
      })
      .id("row3")

      Row() {
        Text('row4')
      }.justifyContent(FlexAlign.Center)
      .backgroundColor('#2ca9e0')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
        left: { anchor: "__container__", align: HorizontalAlign.Start },
        right: { anchor: "row1", align: HorizontalAlign.End }
      })
      .id("row4")

      Row() {
        Text('row5')
      }.justifyContent(FlexAlign.Center)
      .backgroundColor('#30c9f7')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
        left: { anchor: "row2", align: HorizontalAlign.Start },
        right: { anchor: "row2", align: HorizontalAlign.End }
      })
      .id("row5")

      Row() {
        Text('row6')
      }
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#ff33ffb5')
      .alignRules({
        top: { anchor: "row3", align: VerticalAlign.Bottom },
        bottom: { anchor: "row4", align: VerticalAlign.Bottom },
        left: { anchor: "row3", align: HorizontalAlign.Start },
        right: { anchor: "row3", align: HorizontalAlign.End }
      })
      .id("row6")
      .backgroundImagePosition(Alignment.Bottom)
      .backgroundImageSize(ImageSize.Cover)
    }
    .width(300).height(300)
    .margin({ left: 50 })
    .border({ width: 2, color: "#6699FF" })
  }
  .height('100%')
}
}