鸿蒙ArkUI之相对布局容器(RelativeContainer)实战之狼人杀布局,详细介绍相对布局容器的用法,附上代码,以及效果图

在鸿蒙应用开发中,若是遇到布局相对复杂的场景,往往需要嵌套许多层组件,去还原UI图的效果,若是能够掌握相对布局容器的使用,对于复杂的布局场景,可直接减少组件嵌套,且随心所欲完成复杂场景的布局。

官方地址:

RelativeContainer-行列与堆叠-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

 关键属性

RelativeContainer能够帮我们随心所欲完成布局的关键在于,子组件可以通过alignRules这个属性去设置和什么什么组件对齐,通过锚点,去向某一个组件对齐,比如,父组件RelativeContainer()组件,它的锚点必须是:__container__,其他的组件可以通过设置id(接收字符串自定义)的方式来锁定锚点,下面这些参数,就是alignRules属性接收的参数。

名称类型描述
left{ anchor: string, align: HorizontalAlign }

设置左对齐参数。

- anchor:设置作为锚点的组件的id值。

- align:设置相对于锚点组件的对齐方式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

right{ anchor: string, align: HorizontalAlign }

设置右对齐参数。

- anchor:设置作为锚点的组件的id值。

- align:设置相对于锚点组件的对齐方式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

middle{ anchor: string, align: HorizontalAlign }

设置横向居中对齐方式的参数。

- anchor:设置作为锚点的组件的id值。

- align:设置相对于锚点组件的对齐方式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

top{ anchor: string, align: VerticalAlign }

设置顶部对齐的参数。

- anchor:设置作为锚点的组件的id值。

- align:设置相对于锚点组件的对齐方式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

bottom{ anchor: string, align: VerticalAlign }

设置底部对齐的参数。

- anchor:设置作为锚点的组件的id值。

- align:设置相对于锚点组件的对齐方式。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

center{ anchor: string, align: VerticalAlign }

设置纵向居中对齐方式的参数。

元服务API: 从API version 11开始,该接口支持在元服务中使用。

 用法

下面代码块所示:在RelativeContainer中有一个子组件,它的alignRules设置了顶部对齐RelativeContainer容器的顶部,左边对齐RelativeContainer的左边,为啥是RelativeContainer,因为,对齐的锚点是__contanier__,它就代表RelativeContainer容器,像其他子组件若是要向这个子组件对齐,就可以通过,这个组件绑定的id(img1)作为锚点,设置对齐方式

  
  RelativeContainer() {
     Column({ space: 2 }) {
            Image($r('app.media.nvwu'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('女巫')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img1')
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 80, left: 15 })
      }

 像下面这个代码块,img2这个组件,就是相对img1,和RelativeContainer设置的对齐方式

 RelativeContainer() {
          Text('狼人杀')
            .fontSize(20)
            .fontWeight(700)
            .alignRules({
              middle: { anchor: '__container__', align: HorizontalAlign.Center }
            })
            .margin({ top: 20 })
          Column({ space: 2 }) {
            Image($r('app.media.nvwu'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('女巫')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img1')
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 80, left: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.langren'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('狼人')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img2')
          .alignRules({
            top: { anchor: 'img1', align: VerticalAlign.Bottom }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 20, left: 15 })
         }

注意点

加了组件,就必须给它设置对齐方式否则,组件将默认堆积在容器的左上角,组件margin的方向,也会跟着对齐方式的方向走,比如img2的上边,是对着img1的下边,img2的margin({top:10}) 就会对着img1的下边走10vp

完整代码

下面是一个简单的布局,给RelativeContainer的一级子组件都加上了id,也调整了对齐方式,img1到img4的左边,相对RelativeContainer的左边对齐,img5到img8的右边相对于RelativeContainer的右边对齐,img1的顶部相对于RelativeContainer的顶部对齐,img2到img4的顶部相对于前一个img的底部对齐,img5的顶部相对于RelativeContainer的顶部对齐,img6到img8的顶部相对于前一个img的底部对齐。

@Preview
@Component
export struct RelativeContainerCase {
  build() {
    NavDestination() {
      Column({ space: 20 }) {
        RelativeContainer() {
          Text('狼人杀')
            .fontSize(20)
            .fontWeight(700)
            .alignRules({
              middle: { anchor: '__container__', align: HorizontalAlign.Center }
            })
            .margin({ top: 20 })
          Column({ space: 2 }) {
            Image($r('app.media.nvwu'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('女巫')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img1')
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 80, left: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.langren'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('狼人')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img2')
          .alignRules({
            top: { anchor: 'img1', align: VerticalAlign.Bottom }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 20, left: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.lieren'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('猎人')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img3')
          .alignRules({
            top: { anchor: 'img2', align: VerticalAlign.Bottom }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 20, left: 15 })

          Column({ space: 2 }) {
            Image($r("app.media.pingmin"))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('平民')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img4')
          .alignRules({
            top: { anchor: 'img3', align: VerticalAlign.Bottom }
          , left: { anchor: '__container__', align: HorizontalAlign.Start }
          })
          .margin({ top: 20, left: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.yvyanjia'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('预言家')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img5')
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top }
          , right: { anchor: '__container__', align: HorizontalAlign.End }
          })
          .margin({ top: 80, right: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.pingmin'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('平民')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img6')

          .alignRules({
            top: { anchor: 'img5', align: VerticalAlign.Bottom }
          , right: { anchor: '__container__', align: HorizontalAlign.End }
          })
          .margin({ top: 20, right: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.langren'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('狼人')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img7')
          .alignRules({
            top: { anchor: 'img6', align: VerticalAlign.Bottom }
          , right: { anchor: '__container__', align: HorizontalAlign.End }
          })
          .margin({ top: 20, right: 15 })

          Column({ space: 2 }) {
            Image($r('app.media.langren'))
              .height(40)
              .width(40)
              .borderRadius(20)
            Text('狼人')
              .fontWeight(700)
              .fontSize(12)
          }
          .id('img8')
          .alignRules({
            top: { anchor: 'img7', align: VerticalAlign.Bottom }
          , right: { anchor: '__container__', align: HorizontalAlign.End }
          })
          .margin({ top: 20, right: 15 })

        }
        .borderRadius(10)
        .backgroundColor('#ccc')
      }
      .justifyContent(FlexAlign.Center)
      .height('100%')
      .width('100%')
    }.height('100%')
    .width('100%')
    .title('展示RelativeContainer')
  }
}


@Builder
function RelativeContainerCaseBuilder() {
  RelativeContainerCase()
}

使用RelativeContainer的好处

对于这种布局,可以使用线性布局来展示,比如:两个Column,或者四个Row,那么用RelativeContainer的好处在哪?

如果使用线性布局,就会多出是组件的嵌套,影响渲染的性能,使用RelativeContainer,可以直接将组件树拍平,提升渲染性能,对于更加复杂的场景,使用RelativeContainer更是可以做到随心所欲布局,只要对照UI设计稿,把控好距离,设置id,我的组件想放那块就放哪块,不需要像线性布局那样考虑如何嵌套才能达到UI效果

 效果展示

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞瓶可乐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值