ArkUI之线性布局--Row、Column

136 阅读10分钟

1.概述

线性布局(LinearLayout)是开发中最常见的布局,通过Row和Column构建。Column容器内元素按照垂直方向排列,Row容器内部元素按照水平方向排列。

2.基础概念

(1) 布局容器:具有布局能力的容器组件,可以承载其他元素作为其子元素,布局容器会对其子元素进行尺寸计算和布局排列。

(2) 布局子元素:布局容器内部的元素。

(3) 主轴:线性布局容器在布局方向上的轴线,子元素默认沿主轴排列。Row容器主轴为水平方向,Column容器主轴为垂直方向。

(4) 交叉轴:垂直于主轴方向的轴线。Row容器交叉轴为垂直方向,Column容器交叉轴为水平方向。

(5) 间距:布局子元素的间距。

3.布局元素在排列方向上的间距

在布局容器内,可以通过space属性设置排列方向上子元素的间距,使各子元素在排列方向上有等间距效果。

(1) Column容器内排列方向上的间距

image.png

(2)Row容器内排列方向上的间距

image.png

下面通过代码去演示以下space在Column和Row中的使用:

Column() {
  Column({ space: 20 }) {
    Row().width(100).height(50).backgroundColor(Color.Red)
    Row().width('500px').height(50).backgroundColor(Color.Yellow)
    Row().width('90%').height(50).backgroundColor(Color.Blue)
  }.backgroundColor(Color.Gray).width('100%').margin({
    top: 50
  })

  Row({ space: 20 }) {
    Row().width('5%').height(150).backgroundColor(Color.Orange)

    Row().width('50px').height(150).backgroundColor(Color.Red)

    Row().width(30).height(150).backgroundColor(Color.Black)

  }.width('100%').margin({ top: 50 }).padding({
    top: 20,
    bottom: 20
  }).backgroundColor(Color.Pink)
}
.width('100%')

通过预览,我们可以看到效果:

image.png

4.布局子元素在交叉轴上的对齐方式

在布局容器内,可以通过alignItems设置子元素在交叉轴上的对齐方式。其中,交叉轴为垂直方向时,取值为VerticalAlign类型,水平方向取值为HorizontalAlign。

alignSelf属性用于控制单个子元素在容器交叉轴上的对齐方式,优先级高于alignItems属性,如果设置了alignSelf属性,则在单个元素上会覆盖alignItems属性。

(1) Column容器内子元素在水平方向上的排列

image.png

(2)Row容器内子元素在垂直方向上的排列

image.png

Column() {
  //1.HorizontalAlign.Start  子元素在水平方向左对齐
  Column() {
    Row().width(200).height(15).backgroundColor(Color.Blue)
    Row().width(200).height(15).backgroundColor(Color.Red)
    Row().width(200).height(15).backgroundColor(Color.Gray)
  }.width('100%').alignItems(HorizontalAlign.Start)

  //2.HorizontalAlign.Center  子元素在水平方居中对齐
  Column() {
    Row().width(200).height(15).backgroundColor(Color.Blue)
    Row().width(200).height(15).backgroundColor(Color.Red)
    Row().width(200).height(15).backgroundColor(Color.Gray)
  }.width('100%').alignItems(HorizontalAlign.Center).margin({ top: 10 })

  //3.HorizontalAlign.End  子元素在水平方向右对齐
  Column() {
    Row().width(200).height(15).backgroundColor(Color.Blue)
    Row().width(200).height(15).backgroundColor(Color.Red)
    Row().width(200).height(15).backgroundColor(Color.Gray)
  }.width('100%').alignItems(HorizontalAlign.End).margin({ top: 10 })

  //1.VerticalAlign.Top:子元素在垂直方向顶部对齐
  Row() {
    Column().width('10%').height(10).backgroundColor(Color.Green)
    Column().width('10%').height(20).backgroundColor(Color.Blue)
    Column().width('10%').height(30).backgroundColor(Color.Red)
  }
  .height(50)
  .width('100%')
  .backgroundColor(Color.Gray)
  .alignItems(VerticalAlign.Top)
  .margin({
    top: 10
  })

  //2.VerticalAlign.Center:子元素在垂直方向居中对齐
  Row() {
    Column().width('10%').height(10).backgroundColor(Color.Green)
    Column().width('10%').height(20).backgroundColor(Color.Blue)
    Column().width('10%').height(30).backgroundColor(Color.Red)
  }
  .height(50)
  .width('100%')
  .backgroundColor(Color.Gray)
  .alignItems(VerticalAlign.Center)
  .margin({
    top: 10
  })

  //3.VerticalAlign.Bottom:子元素在垂直方向底部对齐
  Row() {
    Column().width('10%').height(10).backgroundColor(Color.Green)
    Column().width('10%').height(20).backgroundColor(Color.Blue)
    Column().width('10%').height(30).backgroundColor(Color.Red)
  }
  .height(50)
  .width('100%')
  .backgroundColor(Color.Gray)
  .alignItems(VerticalAlign.Bottom)
  .margin({
    top: 10
  })

}
.width('100%')

image.png

5.布局子元素在主轴上的排列方式

在布局容器内,可以通过justifyContent属性设置子元素在容器主轴上的排列方式。可以从主轴起始位置开始排布,也可以从主轴结束位置开始排布,或者均匀分割主轴的空间。

(1)Column容器内子元素在垂直方向上的排列

image.png

(2)Row容器内子元素在水平方向上的排列

image.png

Column() {
  Row() {
    //1.FlexAlign.Start:元素在垂直方向方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }.width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .justifyContent(FlexAlign.Start)

    //2.FlexAlign.Center:元素在垂直方向方向中心对齐,第一个元素与行首的距离与最后一个元素与行尾距离相同。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }
    .width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .margin({
      left: 5
    })
    .justifyContent(FlexAlign.Center)

    //3.FlexAlign.End:元素在垂直方向方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }
    .width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .margin({
      left: 5
    })
    .justifyContent(FlexAlign.End)

    //4.FlexAlign.SpaceBetween: 垂直方向均匀分配元素,相邻元素之间距离相同。第一个元素与行首对齐,最后一个元素与行尾对齐。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }
    .width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .margin({
      left: 5
    })
    .justifyContent(FlexAlign.SpaceBetween)

    //5.FlexAlign.SpaceAround: 垂直方向均匀分配元素,相邻元素之间距离相同。第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }
    .width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .margin({
      left: 5
    })
    .justifyContent(FlexAlign.SpaceAround)

    //5.FlexAlign.SpaceEvenly: 垂直方向均匀分配元素,相邻元素之间的距离、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样。
    Column() {
      Row().height(10).width(30).backgroundColor(Color.Red)
      Row().height(10).width(30).backgroundColor(Color.Blue)
      Row().height(10).width(30).backgroundColor(Color.Green)
    }
    .width('14%')
    .height('100%')
    .backgroundColor(Color.Gray)
    .margin({
      left: 5
    })
    .justifyContent(FlexAlign.SpaceEvenly)

  }.width('100%').height(60)

  Column() {
    Row() {
      //1.FlexAlign.Start:元素在水平方向首端对齐,第一个元素与行首对齐,同时后续的元素与前一个对齐。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.Start)

      //2.FlexAlign.Center:元素在水平方向中心对齐,第一个元素与行首的距离与最后一个元素与行尾距离相同。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.Center)
    }.width('100%').height(80).justifyContent(FlexAlign.SpaceBetween)

    Row() {
      //3.FlexAlign.End:元素在水平方向尾部对齐,最后一个元素与行尾对齐,其他元素与后一个对齐。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.End)

      //4.FlexAlign.SpaceBetween:水平方向均匀分配元素,相邻元素之间距离相同。第一个元素与行首对齐,最后一个元素与行尾对齐。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.SpaceBetween)
    }.width('100%').height(80).justifyContent(FlexAlign.SpaceBetween)
    .margin({
      top: 10
    })

    Row() {
      //5.FlexAlign.SpaceAround:水平方向均匀分配元素,相邻元素之间距离相同。第一个元素到行首的距离和最后一个元素到行尾的距离是相邻元素之间距离的一半。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.SpaceAround)

      //6.FlexAlign.SpaceEvenly:水平方向均匀分配元素,相邻元素之间的距离、第一个元素与行首的间距、最后一个元素到行尾的间距都完全一样。
      Row() {
        Column().height('100%').width(30).backgroundColor(Color.Red)
        Column().height('100%').width(30).backgroundColor(Color.Green)
        Column().height('100%').width(30).backgroundColor(Color.Yellow)
      }.width('48%').height('100%').backgroundColor(Color.Gray).justifyContent(FlexAlign.SpaceEvenly)
    }.width('100%').height(80).justifyContent(FlexAlign.SpaceBetween).margin({
      top: 10
    })

  }.width('100%').margin({
    top: 10
  })
}
.width('100%')

image.png

6.自适应拉伸

在线性布局下,常用空白填充组件Blank,在容器主轴方向自动填充空白空间,达到自适应拉伸效果。Row和Column作为容器,只需要添加宽高为百分比,当屏幕宽高发生变化时,会产生自适应效果。

Column() {
  Column() {
    Row() {
      Text('左边的Text')
      Blank()
      Text('右边的文字')
    }.width('100%').padding(10).backgroundColor(Color.White).borderRadius(10)
  }.width('100%').padding(20).backgroundColor(Color.Pink)
}
.width('100%')

image.png

7.自适应缩放

自适应缩放是指子元素随容器尺寸的变化而按照预设的比例自动调整尺寸,适应各种不同大小的设备。在线性布局中,可以使用以下两种方法实现自适应缩放。

(1)父容器尺寸确定时,使用layoutWeight属性设置子元素和兄弟元素在主轴上的权重,忽略元素本身尺寸设置,使它们在任意尺寸的设备下自适应占满剩余空间。 (2)父容器尺寸确定时,使用百分比设置子元素和兄弟元素的宽度,使他们在任意尺寸的设备下保持固定的自适应占比。

Column() {
  Column() {

    //1.父容器尺寸确定时,使用layoutWeight属性设置子元素和兄弟元素在主轴上的权重
    Row() {
      Column() {

      }.layoutWeight(1).height('50%').backgroundColor(Color.Red)

      Column() {

      }.layoutWeight(2).height('80%').backgroundColor(Color.Green)

      Column() {

      }.layoutWeight(3).height('100%').backgroundColor(Color.Blue)

    }.height('50%').backgroundColor(Color.Pink)

    //2.父容器尺寸确定时,使用百分比设置子元素和兄弟元素的宽度
    Row() {
      Column() {

      }.width('20%').height('50%').backgroundColor(Color.Red)

      Column() {

      }.width('30%').height('80%').backgroundColor(Color.Green)

      Column() {

      }.width('50%').height('100%').backgroundColor(Color.Black)

    }.height('50%').backgroundColor(Color.Orange)

  }.height(200).backgroundColor(Color.Gray)
}
.width('100%')

image.png

8.自适应延伸

自适应延伸是指在不同尺寸设备下,当页面的内容超出屏幕大小而无法完全显示时,可以通过滚动条进行拖动展示。这种方法适用于线性布局中内容无法一屏展示的场景。通常有以下两种实现方式。

(1)在List中添加滚动条:当List子项过多一屏放不下时,可以将每一项子元素放置在不同的组件中,通过滚动条进行拖动展示。可以通过scrollBar属性设置滚动条的常驻状态,edgeEffect属性设置拖动到内容最末端的回弹效果。

(2)使用Scroll组件:在线性布局中,开发者可以进行垂直方向或者水平方向的布局。当一屏无法完全显示时,可以在Column或Row组件的外层包裹一个可滚动的容器组件Scroll来实现可滑动的线性布局。 垂直方向布局中使用Scroll组件

竖直方向布局中使用Scroll组件:

@Component
struct Demo6 {
  scroller: Scroller = new Scroller();
  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

  build() {
    Scroll(this.scroller) {
      Column() {
        ForEach(this.arr, (item?: number | undefined) => {
          if (item) {
            Text(item.toString())
              .width('90%')
              .height(150)
              .backgroundColor(0xFFFFFF)
              .borderRadius(15)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .margin({ top: 10 })
          }
        }, (item: number) => item.toString())
      }.width('100%')
    }
    .backgroundColor(0xDCDCDC)
    .scrollable(ScrollDirection.Vertical) // 滚动方向为垂直方向
    .scrollBar(BarState.On) // 滚动条常驻显示
    .scrollBarColor(Color.Gray) // 滚动条颜色
    .scrollBarWidth(10) // 滚动条宽度
    .edgeEffect(EdgeEffect.Spring) // 滚动到边沿后回弹
  }
}

image.png

水平方向布局中添加Scroll组件

@Component
struct Demo7 {
  scroller: Scroller = new Scroller();
  private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

  build() {
    Scroll(this.scroller) {
      Row() {
        ForEach(this.arr, (item?: number | undefined) => {
          if (item) {
            Text(item.toString())
              .height('90%')
              .width(150)
              .backgroundColor(0xFFFFFF)
              .borderRadius(15)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .margin({ left: 10 })
          }
        })
      }.height('100%')
    }
    .backgroundColor(0xDCDCDC)
    .scrollable(ScrollDirection.Horizontal) // 滚动方向为水平方向
    .scrollBar(BarState.On) // 滚动条常驻显示
    .scrollBarColor(Color.Gray) // 滚动条颜色
    .scrollBarWidth(10) // 滚动条宽度
    .edgeEffect(EdgeEffect.Spring) // 滚动到边沿后回弹
  }
}

image.png

Column和Row作为最常用的布局组件,需要熟练掌握,才能提升开发的效率。