線性布局(Row/Column)

2024-01-25 13:10 更新

概述

線性布局(LinearLayout)是開(kāi)發(fā)中最常用的布局,通過(guò)線性容器RowColumn構(gòu)建。線性布局是其他布局的基礎(chǔ),其子元素在線性方向上(水平方向和垂直方向)依次排列。線性布局的排列方向由所選容器組件決定,Column容器內(nèi)子元素按照垂直方向排列,Row容器內(nèi)子元素按照水平方向排列。根據(jù)不同的排列方向,開(kāi)發(fā)者可選擇使用Row或Column容器創(chuàng)建線性布局。

圖1 Column容器內(nèi)子元素排列示意圖
圖2 Row容器內(nèi)子元素排列示意圖

基本概念

  • 布局容器:具有布局能力的容器組件,可以承載其他元素作為其子元素,布局容器會(huì)對(duì)其子元素進(jìn)行尺寸計(jì)算和布局排列。
  • 布局子元素:布局容器內(nèi)部的元素。
  • 主軸:線性布局容器在布局方向上的軸線,子元素默認(rèn)沿主軸排列。Row容器主軸為水平方向,Column容器主軸為垂直方向。
  • 交叉軸:垂直于主軸方向的軸線。Row容器交叉軸為垂直方向,Column容器交叉軸為水平方向。
  • 間距:布局子元素的間距。

布局子元素在排列方向上的間距

在布局容器內(nèi),可以通過(guò)space屬性設(shè)置排列方向上子元素的間距,使各子元素在排列方向上有等間距效果。

Column容器內(nèi)排列方向上的間距

圖3 Column容器內(nèi)排列方向的間距圖
  1. Column({ space: 20 }) {
  2. Text('space: 20').fontSize(15).fontColor(Color.Gray).width('90%')
  3. Row().width('90%').height(50).backgroundColor(0xF5DEB3)
  4. Row().width('90%').height(50).backgroundColor(0xD2B48C)
  5. Row().width('90%').height(50).backgroundColor(0xF5DEB3)
  6. }.width('100%')

Row容器內(nèi)排列方向上的間距

圖4 Row容器內(nèi)排列方向的間距圖
  1. Row({ space: 35 }) {
  2. Text('space: 35').fontSize(15).fontColor(Color.Gray)
  3. Row().width('10%').height(150).backgroundColor(0xF5DEB3)
  4. Row().width('10%').height(150).backgroundColor(0xD2B48C)
  5. Row().width('10%').height(150).backgroundColor(0xF5DEB3)
  6. }.width('90%')

布局子元素在交叉軸上的對(duì)齊方式

在布局容器內(nèi),可以通過(guò)alignItems屬性設(shè)置子元素在交叉軸(排列方向的垂直方向)上的對(duì)齊方式。且在各類(lèi)尺寸屏幕中,表現(xiàn)一致。其中,交叉軸為垂直方向時(shí),取值為VerticalAlign類(lèi)型,水平方向取值為HorizontalAlign

alignSelf屬性用于控制單個(gè)子元素在容器交叉軸上的對(duì)齊方式,其優(yōu)先級(jí)高于alignItems屬性,如果設(shè)置了alignSelf屬性,則在單個(gè)子元素上會(huì)覆蓋alignItems屬性。

Column容器內(nèi)子元素在水平方向上的排列

圖5 Column容器內(nèi)子元素在水平方向上的排列圖
  • HorizontalAlign.Start:子元素在水平方向左對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').alignItems(HorizontalAlign.Start).backgroundColor('rgb(242,242,242)')

  • HorizontalAlign.Center:子元素在水平方向居中對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').alignItems(HorizontalAlign.Center).backgroundColor('rgb(242,242,242)')

  • HorizontalAlign.End:子元素在水平方向右對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').alignItems(HorizontalAlign.End).backgroundColor('rgb(242,242,242)')

Row容器內(nèi)子元素在垂直方向上的排列

圖6 Row容器內(nèi)子元素在垂直方向上的排列圖
  • VerticalAlign.Top:子元素在垂直方向頂部對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).alignItems(VerticalAlign.Top).backgroundColor('rgb(242,242,242)')

  • VerticalAlign.Center:子元素在垂直方向居中對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).alignItems(VerticalAlign.Center).backgroundColor('rgb(242,242,242)')

  • VerticalAlign.Bottom:子元素在垂直方向底部對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).alignItems(VerticalAlign.Bottom).backgroundColor('rgb(242,242,242)')

布局子元素在主軸上的排列方式

在布局容器內(nèi),可以通過(guò)justifyContent屬性設(shè)置子元素在容器主軸上的排列方式??梢詮闹鬏S起始位置開(kāi)始排布,也可以從主軸結(jié)束位置開(kāi)始排布,或者均勻分割主軸的空間。

Column容器內(nèi)子元素在垂直方向上的排列

圖7 Column容器內(nèi)子元素在垂直方向上的排列圖
  • justifyContent(FlexAlign.Start):元素在垂直方向首端對(duì)齊,第一個(gè)元素與行首對(duì)齊,同時(shí)后續(xù)的元素與前一個(gè)對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.Start)

  • justifyContent(FlexAlign.Center):元素在垂直方向中心對(duì)齊,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.Center)

  • justifyContent(FlexAlign.End):元素在垂直方向尾部對(duì)齊,最后一個(gè)元素與行尾對(duì)齊,其他元素與后一個(gè)對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.End)

  • justifyContent(FlexAlign.Spacebetween):垂直方向均勻分配元素,相鄰元素之間距離相同。第一個(gè)元素與行首對(duì)齊,最后一個(gè)元素與行尾對(duì)齊。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceBetween)

  • justifyContent(FlexAlign.SpaceAround):垂直方向均勻分配元素,相鄰元素之間距離相同。第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離是相鄰元素之間距離的一半。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceAround)

  • justifyContent(FlexAlign.SpaceEvenly):垂直方向均勻分配元素,相鄰元素之間的距離、第一個(gè)元素與行首的間距、最后一個(gè)元素到行尾的間距都完全一樣。
    1. Column({}) {
    2. Column() {
    3. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('80%').height(50).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('80%').height(50).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(300).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceEvenly)

Row容器內(nèi)子元素在水平方向上的排列

圖8 Row容器內(nèi)子元素在水平方向上的排列圖
  • justifyContent(FlexAlign.Start):元素在水平方向方向首端對(duì)齊,第一個(gè)元素與行首對(duì)齊,同時(shí)后續(xù)的元素與前一個(gè)對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.Start)

  • justifyContent(FlexAlign.Center):元素在水平方向方向中心對(duì)齊,第一個(gè)元素與行首的距離與最后一個(gè)元素與行尾距離相同。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.Center)

  • justifyContent(FlexAlign.End):元素在水平方向方向尾部對(duì)齊,最后一個(gè)元素與行尾對(duì)齊,其他元素與后一個(gè)對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.End)

  • justifyContent(FlexAlign.Spacebetween):水平方向方向均勻分配元素,相鄰元素之間距離相同。第一個(gè)元素與行首對(duì)齊,最后一個(gè)元素與行尾對(duì)齊。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceBetween)

  • justifyContent(FlexAlign.SpaceAround):水平方向方向均勻分配元素,相鄰元素之間距離相同。第一個(gè)元素到行首的距離和最后一個(gè)元素到行尾的距離是相鄰元素之間距離的一半。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceAround)

  • justifyContent(FlexAlign.SpaceEvenly):水平方向方向均勻分配元素,相鄰元素之間的距離、第一個(gè)元素與行首的間距、最后一個(gè)元素到行尾的間距都完全一樣。
    1. Row({}) {
    2. Column() {
    3. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    4. Column() {
    5. }.width('20%').height(30).backgroundColor(0xD2B48C)
    6. Column() {
    7. }.width('20%').height(30).backgroundColor(0xF5DEB3)
    8. }.width('100%').height(200).backgroundColor('rgb(242,242,242)').justifyContent(FlexAlign.SpaceEvenly)

自適應(yīng)拉伸

在線性布局下,常用空白填充組件Blank,在容器主軸方向自動(dòng)填充空白空間,達(dá)到自適應(yīng)拉伸效果。Row和Column作為容器,只需要添加寬高為百分比,當(dāng)屏幕寬高發(fā)生變化時(shí),會(huì)產(chǎn)生自適應(yīng)效果。

  1. @Entry
  2. @Component
  3. struct BlankExample {
  4. build() {
  5. Column() {
  6. Row() {
  7. Text('Bluetooth').fontSize(18)
  8. Blank()
  9. Toggle({ type: ToggleType.Switch, isOn: true })
  10. }.backgroundColor(0xFFFFFF).borderRadius(15).padding({ left: 12 }).width('100%')
  11. }.backgroundColor(0xEFEFEF).padding(20).width('100%')
  12. }
  13. }
圖9 豎屏
圖10 橫屏

自適應(yīng)縮放

自適應(yīng)縮放是指子組件隨容器尺寸的變化而按照預(yù)設(shè)的比例自動(dòng)調(diào)整尺寸,適應(yīng)各種不同大小的設(shè)備。在線性布局中,可以使用以下兩種方法實(shí)現(xiàn)自適應(yīng)縮放。

  • 父容器尺寸確定時(shí),使用layoutWeight屬性設(shè)置子組件和兄弟元素在主軸上的權(quán)重,忽略元素本身尺寸設(shè)置,使它們?cè)谌我獬叽绲脑O(shè)備下自適應(yīng)占滿剩余空間。
    1. @Entry
    2. @Component
    3. struct layoutWeightExample {
    4. build() {
    5. Column() {
    6. Text('1:2:3').width('100%')
    7. Row() {
    8. Column() {
    9. Text('layoutWeight(1)')
    10. .textAlign(TextAlign.Center)
    11. }.layoutWeight(1).backgroundColor(0xF5DEB3).height('100%')
    12. Column() {
    13. Text('layoutWeight(2)')
    14. .textAlign(TextAlign.Center)
    15. }.layoutWeight(2).backgroundColor(0xD2B48C).height('100%')
    16. Column() {
    17. Text('layoutWeight(3)')
    18. .textAlign(TextAlign.Center)
    19. }.layoutWeight(3).backgroundColor(0xF5DEB3).height('100%')
    20. }.backgroundColor(0xffd306).height('30%')
    21. Text('2:5:3').width('100%')
    22. Row() {
    23. Column() {
    24. Text('layoutWeight(2)')
    25. .textAlign(TextAlign.Center)
    26. }.layoutWeight(2).backgroundColor(0xF5DEB3).height('100%')
    27. Column() {
    28. Text('layoutWeight(5)')
    29. .textAlign(TextAlign.Center)
    30. }.layoutWeight(5).backgroundColor(0xD2B48C).height('100%')
    31. Column() {
    32. Text('layoutWeight(3)')
    33. .textAlign(TextAlign.Center)
    34. }.layoutWeight(3).backgroundColor(0xF5DEB3).height('100%')
    35. }.backgroundColor(0xffd306).height('30%')
    36. }
    37. }
    38. }
    圖11 橫屏

    圖12 豎屏

  • 父容器尺寸確定時(shí),使用百分比設(shè)置子組件和兄弟元素的寬度,使他們?cè)谌我獬叽绲脑O(shè)備下保持固定的自適應(yīng)占比。
    1. @Entry
    2. @Component
    3. struct WidthExample {
    4. build() {
    5. Column() {
    6. Row() {
    7. Column() {
    8. Text('left width 20%')
    9. .textAlign(TextAlign.Center)
    10. }.width('20%').backgroundColor(0xF5DEB3).height('100%')
    11. Column() {
    12. Text('center width 50%')
    13. .textAlign(TextAlign.Center)
    14. }.width('50%').backgroundColor(0xD2B48C).height('100%')
    15. Column() {
    16. Text('right width 30%')
    17. .textAlign(TextAlign.Center)
    18. }.width('30%').backgroundColor(0xF5DEB3).height('100%')
    19. }.backgroundColor(0xffd306).height('30%')
    20. }
    21. }
    22. }
    圖13 橫屏
    圖14 豎屏

自適應(yīng)延伸

自適應(yīng)延伸是指在不同尺寸設(shè)備下,當(dāng)頁(yè)面的內(nèi)容超出屏幕大小而無(wú)法完全顯示時(shí),可以通過(guò)滾動(dòng)條進(jìn)行拖動(dòng)展示。這種方法適用于線性布局中內(nèi)容無(wú)法一屏展示的場(chǎng)景。通常有以下兩種實(shí)現(xiàn)方式。

  • 在List中添加滾動(dòng)條:當(dāng)List子項(xiàng)過(guò)多一屏放不下時(shí),可以將每一項(xiàng)子元素放置在不同的組件中,通過(guò)滾動(dòng)條進(jìn)行拖動(dòng)展示。可以通過(guò)scrollBar屬性設(shè)置滾動(dòng)條的常駐狀態(tài),edgeEffect屬性設(shè)置拖動(dòng)到內(nèi)容最末端的回彈效果。
  • 使用Scroll組件:在線性布局中,開(kāi)發(fā)者可以進(jìn)行垂直方向或者水平方向的布局。當(dāng)一屏無(wú)法完全顯示時(shí),可以在Column或Row組件的外層包裹一個(gè)可滾動(dòng)的容器組件Scroll來(lái)實(shí)現(xiàn)可滑動(dòng)的線性布局。
    垂直方向布局中使用Scroll組件:
    1. @Entry
    2. @Component
    3. struct ScrollExample {
    4. scroller: Scroller = new Scroller();
    5. private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    6. build() {
    7. Scroll(this.scroller) {
    8. Column() {
    9. ForEach(this.arr, (item) => {
    10. Text(item.toString())
    11. .width('90%')
    12. .height(150)
    13. .backgroundColor(0xFFFFFF)
    14. .borderRadius(15)
    15. .fontSize(16)
    16. .textAlign(TextAlign.Center)
    17. .margin({ top: 10 })
    18. }, item => item)
    19. }.width('100%')
    20. }
    21. .backgroundColor(0xDCDCDC)
    22. .scrollable(ScrollDirection.Vertical) // 滾動(dòng)方向?yàn)榇怪狈较?/span>
    23. .scrollBar(BarState.On) // 滾動(dòng)條常駐顯示
    24. .scrollBarColor(Color.Gray) // 滾動(dòng)條顏色
    25. .scrollBarWidth(10) // 滾動(dòng)條寬度
    26. .edgeEffect(EdgeEffect.Spring) // 滾動(dòng)到邊沿后回彈
    27. }
    28. }

    水平方向布局中使用Scroll組件:

    1. @Entry
    2. @Component
    3. struct ScrollExample {
    4. scroller: Scroller = new Scroller();
    5. private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    6. build() {
    7. Scroll(this.scroller) {
    8. Row() {
    9. ForEach(this.arr, (item) => {
    10. Text(item.toString())
    11. .height('90%')
    12. .width(150)
    13. .backgroundColor(0xFFFFFF)
    14. .borderRadius(15)
    15. .fontSize(16)
    16. .textAlign(TextAlign.Center)
    17. .margin({ left: 10 })
    18. })
    19. }.height('100%')
    20. }
    21. .backgroundColor(0xDCDCDC)
    22. .scrollable(ScrollDirection.Horizontal) // 滾動(dòng)方向?yàn)樗椒较?/span>
    23. .scrollBar(BarState.On) // 滾動(dòng)條常駐顯示
    24. .scrollBarColor(Color.Gray) // 滾動(dòng)條顏色
    25. .scrollBarWidth(10) // 滾動(dòng)條寬度
    26. .edgeEffect(EdgeEffect.Spring) // 滾動(dòng)到邊沿后回彈
    27. }
    28. }

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)