鴻蒙HarmonyOS實戰-ArkUI元件(Flex)

蜀道山QAQ發表於2024-03-24

🚀一、Flex

🔎1.概述

Flex佈局它可以讓容器中的子元素具有彈性伸縮性。Flex佈局是一種二維佈局模型,它可以在任意方向上對元素進行排列,並且可以動態地調整元素的大小和位置,以適應不同的螢幕尺寸和裝置。透過使用Flex佈局,我們可以實現響應式佈局效果,以適應不同的螢幕尺寸和裝置。Flex佈局主要由容器和專案兩個部分組成,容器是需要進行佈局的元素,專案是容器中的每個子元素。

image

主軸是Flex容器的主要方向,也是子元素排列的方向,通常設定為水平方向。在Flex佈局中,主軸的起點和終點分別為JustifyContent屬性所設定的對齊方式所表示的位置。

交叉軸則與主軸垂直,通常設定為垂直方向。在Flex佈局中,交叉軸與主軸方向相反,它的起點和終點分別是AlignContent屬性所設定的對齊方式所表示的位置。

更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

🔎2.佈局方向

在Flex彈性佈局中,主軸和交叉軸的方向可以透過FlexDirection屬性來進行設定。常見的值包括:Row(主軸方向為水平向右)、RowReverse(主軸方向為水平向左)、Column(主軸方向為垂直向下)和ColumnReverse(主軸方向為垂直向上)。

image

🦋2.1 FlexDirection.Row

主軸為水平方向,子元件從起始端沿著水平方向開始排布。

Flex({ direction: FlexDirection.Row }) {
  Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🦋2.2 FlexDirection.RowReverse

主軸為水平方向,子元件從終點端沿著FlexDirection. Row相反的方向開始排布。

Flex({ direction: FlexDirection.RowReverse }) {
  Text('1').width('33%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('33%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🦋2.3 FlexDirection.Column

主軸為垂直方向,子元件從起始端沿著垂直方向開始排布。

Flex({ direction: FlexDirection.Column }) {
  Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🦋2.4 FlexDirection.ColumnReverse

主軸為垂直方向,子元件從起始端沿著垂直方向開始排布。

Flex({ direction: FlexDirection.ColumnReverse }) {
  Text('1').width('100%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('100%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('100%').height(50).backgroundColor(0xF5DEB3)
}
.height(70)
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🔎2.佈局換行

Flex彈性佈局的換行是指將一行上的元素,在到達父容器的邊界時換到下一行繼續排列。這可以透過控制flex-wrap屬性來實現。FlexWrap屬性有三個值:

  1. Nowrap(預設值):不換行,將所有元素排在同一行上。

  2. Wrap:換行,當一行排滿後,將元素放置到下一行上。

  3. WrapReverse:倒序換行,當一行排滿後,將元素從下一行上開始排列。

比如,設定FlexWrap: Wrap;可以讓元素在父容器的邊界處換行,從而實現響應式佈局。

更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

🦋2.1 FlexWrap.NoWrap

不換行。如果子元件的寬度總和大於父元素的寬度,則子元件會被壓縮寬度。

Flex({ wrap: FlexWrap.NoWrap }) {
  Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
} 
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🦋2.2 FlexWrap.Wrap

換行,每一行子元件按照主軸方向排列。

Flex({ wrap: FlexWrap.Wrap }) {
  Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('50%').height(50).backgroundColor(0xD2B48C)
} 
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🦋2.3 FlexWrap. WrapReverse

換行,每一行子元件按照主軸反方向排列。

Flex({ wrap: FlexWrap.WrapReverse}) {
  Text('1').width('50%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('50%').height(50).backgroundColor(0xD2B48C)
  Text('3').width('50%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding(10)
.backgroundColor(0xAFEEEE)

image

🔎3.對齊方式

🦋3.1 主軸對齊方式

image

Flex彈性佈局的主軸對齊方式有以下幾種:

  1. justifyContent: FlexAlign.Start:預設值,主軸開始端對齊;
  2. justifyContent: FlexAlign.End:主軸結束端對齊;
  3. justifyContent: FlexAlign.Center:主軸居中對齊;
  4. justifyContent: FlexAlign.SpaceBetween:元素之間平均分佈,首尾元素與容器邊框之間無空隙;
  5. justifyContent: FlexAlign.SpaceAround:元素平均分佈,各元素周圍留有相等的空隙;
  6. justifyContent: FlexAlign.SpaceEvenly:元素平均分佈,每個元素周圍留有相等的空隙,首尾元素距離容器邊框的距離是其他元素的兩倍。
☀️3.1.1 FlexAlign.Start

子元件在主軸方向起始端對齊, 第一個子元件與父元素邊沿對齊,其他元素與前一個元素對齊。

Flex({ justifyContent: FlexAlign.Start }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)    
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

☀️3.1.2 FlexAlign.Center

子元件在主軸方向居中對齊。

Flex({ justifyContent: FlexAlign.Center }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)  
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)   
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

☀️3.1.3 FlexAlign.End

子元件在主軸方向終點端對齊, 最後一個子元件與父元素邊沿對齊,其他元素與後一個元素對齊。

Flex({ justifyContent: FlexAlign.End }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)  
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)   
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

☀️3.1.4 FlexAlign.SpaceBetween

Flex主軸方向均勻分配彈性元素,相鄰子元件之間距離相同。第一個子元件和最後一個子元件與父元素邊沿對齊。

Flex({ justifyContent: FlexAlign.SpaceBetween }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)  
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)   
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

☀️3.1.5 FlexAlign.SpaceAround

Flex主軸方向均勻分配彈性元素,相鄰子元件之間距離相同。第一個子元件到主軸起始端的距離和最後一個子元件到主軸終點端的距離是相鄰元素之間距離的一半。

Flex({ justifyContent: FlexAlign.SpaceAround }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)  
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)   
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

☀️3.1.6 FlexAlign.SpaceEvenly

Flex主軸方向元素等間距佈局,相鄰子元件之間的間距、第一個子元件與主軸起始端的間距、最後一個子元件到主軸終點端的間距均相等。

Flex({ justifyContent: FlexAlign.SpaceEvenly }) {  
  Text('1').width('20%').height(50).backgroundColor(0xF5DEB3)  
  Text('2').width('20%').height(50).backgroundColor(0xD2B48C)   
  Text('3').width('20%').height(50).backgroundColor(0xF5DEB3)
}
.width('90%')
.padding({ top: 10, bottom: 10 })
.backgroundColor(0xAFEEEE)

image

🦋3.2 交叉軸對齊方式

Flex彈性佈局的交叉軸對齊方式包括以下幾種:

  1. ItemAlign.Start:交叉軸起點對齊;
  2. ItemAlign.Center:交叉軸中點對齊;
  3. ItemAlign.End:交叉軸終點對齊;
  4. ItemAlign. Baseline:以第一行文字的基線對齊;
  5. ItemAlign.Stretch:預設值,每個子元素都延伸到交叉軸的相同大小。
☀️3.2.1 ItemAlign.Auto

使用Flex容器中預設配置。

Flex({ alignItems: ItemAlign.Auto }) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.2 ItemAlign.Start

交叉軸方向首部對齊

Flex({ alignItems: ItemAlign.Start }) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.3 ItemAlign.Center

交叉軸方向居中對齊

Flex({ alignItems: ItemAlign.Center }) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.4 ItemAlign.End

交叉軸方向底部對齊

Flex({ alignItems: ItemAlign.End }) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.5 ItemAlign.Stretch

交叉軸方向拉伸填充,在未設定尺寸時,拉伸到容器尺寸。

Flex({ alignItems: ItemAlign.Stretch}) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.6 ItemAlign.Baseline

交叉軸方向文字基線對齊

Flex({ alignItems: ItemAlign.Baseline}) {  
  Text('1').width('33%').height(30).backgroundColor(0xF5DEB3)  
  Text('2').width('33%').height(40).backgroundColor(0xD2B48C)  
  Text('3').width('33%').height(50).backgroundColor(0xF5DEB3)
}
.size({ width: '90%', height: 80 })
.padding(10)
.backgroundColor(0xAFEEEE)

image

☀️3.2.7 alignSelf

子元件的alignSelf屬性也可以設定子元件在父容器交叉軸的對齊格式,且會覆蓋Flex佈局容器中alignItems配置。如下例所示:

Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { // 容器元件設定子元件居中
  Text('alignSelf Start').width('25%').height(80)
    .alignSelf(ItemAlign.Start)
    .backgroundColor(0xF5DEB3)
  Text('alignSelf Baseline')
    .alignSelf(ItemAlign.Baseline)
    .width('25%')
    .height(80)
    .backgroundColor(0xD2B48C)
  Text('alignSelf Baseline').width('25%').height(100)
    .backgroundColor(0xF5DEB3)
    .alignSelf(ItemAlign.Baseline)
  Text('no alignSelf').width('25%').height(100)
    .backgroundColor(0xD2B48C)
  Text('no alignSelf').width('25%').height(100)
    .backgroundColor(0xF5DEB3)
}.width('90%').height(220).backgroundColor(0xAFEEEE)

image

🚀二、案例

🔎1.多行內容對齊

🦋1.1 Start

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.Start }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)          

image

🦋1.2 Center

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.Center }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)          

image

🦋1.3 End

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.End }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)

image

🦋1.4 SpaceBetween

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceBetween }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)

image

🦋1.5 SpaceAround

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceAround }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)

image

🦋1.6 SpaceEvenly

Flex({ justifyContent: FlexAlign.SpaceBetween, wrap: FlexWrap.Wrap, alignContent: FlexAlign.SpaceEvenly }) {
  Text('1').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('2').width('60%').height(20).backgroundColor(0xD2B48C)
  Text('3').width('40%').height(20).backgroundColor(0xD2B48C)
  Text('4').width('30%').height(20).backgroundColor(0xF5DEB3)
  Text('5').width('20%').height(20).backgroundColor(0xD2B48C)
}
.width('90%')
.height(100)
.backgroundColor(0xAFEEEE)

image

🔎2.自適應拉伸

🦋2.1 flexBasis

設定子元件在父容器主軸方向上的基準尺寸。如果設定了該值,則子項佔用的空間為設定的值;如果沒設定該屬性,那子項的空間為width/height的值。

更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

Flex() {
  Text('flexBasis("auto")')
    .flexBasis('auto') // 未設定width以及flexBasis值為auto,內容自身寬鬆
    .height(100)
    .backgroundColor(0xF5DEB3)
  Text('flexBasis("auto")' + ' width("40%")')
    .width('40%')
    .flexBasis('auto') //設定width以及flexBasis值auto,使用width的值
    .height(100)
    .backgroundColor(0xD2B48C)

  Text('flexBasis(100)') // 未設定width以及flexBasis值為100,寬度為100vp
    .fontSize(15)
    .flexBasis(100)
    .height(100)
    .backgroundColor(0xF5DEB3)

  Text('flexBasis(100)')
    .fontSize(15)
    .flexBasis(100)
    .width(200) // flexBasis值為100,覆蓋width的設定值,寬度為100vp
    .height(100)
    .backgroundColor(0xD2B48C)
}.width('90%').height(120).padding(10).backgroundColor(0xAFEEEE)

image

🦋2.2 flexGrow

設定父容器的剩餘空間分配給此屬性所在元件的比例。用於“瓜分”父元件的剩餘空間。

Flex() {
Text('flexGrow(2)')
  .flexGrow(2) 
  .width(100)
  .height(100)
  .backgroundColor(0xF5DEB3)

Text('flexGrow(3)')
  .flexGrow(3)
  .width(100)
  .height(100)
  .backgroundColor(0xD2B48C)

Text('no flexGrow')
  .width(100) 
  .height(100)
  .backgroundColor(0xF5DEB3)
}.width(400).height(120).padding(10).backgroundColor(0xAFEEEE)

image

父容器寬度400vp,三個子元件原始寬度為100vp,總和300vp,剩餘空間100vp根據flexGrow值的佔比分配給子元件,未設定flexGrow的子元件不參與“瓜分”。

第一個元素以及第二個元素以2:3分配剩下的100vp。第一個元素為100vp+100vp2/5=140vp,第二個元素為100vp+100vp3/5=160vp。

更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

🦋2.3 flexShrink

當父容器空間不足時,子元件的壓縮比例。

Flex({ direction: FlexDirection.Row }) {
  Text('flexShrink(3)')
    .fontSize(15)
    .flexShrink(3)
    .width(200)
    .height(100)
    .backgroundColor(0xF5DEB3)

  Text('no flexShrink')
    .width(200)
    .height(100)
    .backgroundColor(0xD2B48C)

  Text('flexShrink(2)')
    .flexShrink(2)
    .width(200)
    .height(100)
    .backgroundColor(0xF5DEB3)
}.width(400).height(120).padding(10).backgroundColor(0xAFEEEE)

image

🦋2.4 案例

@Entry  
@Component
struct FlexExample {
  build() {
    Column() {
      Column({ space: 5 }) {
        Flex({ direction: FlexDirection.Row, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
          Text('1').width('30%').height(50).backgroundColor(0xF5DEB3)
          Text('2').width('30%').height(50).backgroundColor(0xD2B48C)
          Text('3').width('30%').height(50).backgroundColor(0xF5DEB3)
        }
        .height(70)
        .width('90%')
        .backgroundColor(0xAFEEEE)
      }.width('100%').margin({ top: 5 })
    }.width('100%') 
 }
}

image

🚀寫在最後

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
  • 更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

相關文章