文章目录alignItems 和 alignContent 的区别alignContent 的取值完整 DemoalignContent 的生效条件小结alignItems 和 alignContent 的区别学 Flex 的时候这两个属性特别容易搞混。alignItems控制每行内各子项在交叉轴上的对齐方式居中/顶部/底部。alignContent控制多行整体在容器交叉轴上的分布方式只有在容器开启了FlexWrap.Wrap换行并且高度大于实际内容高度时才生效。打个比方一排书架alignItems控制每本书放多高多排书架alignContent控制多排书架在整个书柜里如何分布——靠上、靠下、均匀分布还是中间集中。在 PC 端可用空间比手机端大很多多行内容在高度方向上的分布就更加重要。alignContent在 PC 端应用里的使用场景比手机端更多。alignContent 的取值// 在 Flex 容器上设置需要 wrap: FlexWrap.WrapFlex({wrap:FlexWrap.Wrap,alignContent:FlexAlign.Start}){...}取值效果FlexAlign.Start多行集中在交叉轴起始端默认FlexAlign.Center多行集中在交叉轴中间FlexAlign.End多行集中在交叉轴末端FlexAlign.SpaceBetween多行两端对齐中间均匀分布FlexAlign.SpaceAround每行两侧等距首尾有半格间距FlexAlign.SpaceEvenly所有间距包括首尾均等完整 Demo新建文件PcAlignContentPage.etsinterfaceSkill{name:stringlevel:string// expert | proficient | familiarcolor:string}interfacealignOptionsParams{label:string,value:FlexAlign,desc:string}EntryComponentstruct PcAlignContentPage{StatecurrentAlign:FlexAlignFlexAlign.StartStatecontainerHeight:number300StateshowExplain:booleantrueprivatealignOptions:alignOptionsParams[][{label:Start,value:FlexAlign.Start,desc:多行从顶部开始向下排列底部留空},{label:Center,value:FlexAlign.Center,desc:多行整体居中上下等距留空},{label:End,value:FlexAlign.End,desc:多行集中在底部顶部留空},{label:SpaceBetween,value:FlexAlign.SpaceBetween,desc:首行和末行贴边中间均匀分布},{label:SpaceAround,value:FlexAlign.SpaceAround,desc:每行两侧等距首尾有半格间距},{label:SpaceEvenly,value:FlexAlign.SpaceEvenly,desc:包括首尾在内所有间距完全相等},]privateskills:Skill[][{name:ArkTS,level:expert,color:#0A59F7},{name:ArkUI,level:expert,color:#0A59F7},{name:HarmonyOS PC,level:proficient,color:#00B578},{name:Flex 布局,level:expert,color:#0A59F7},{name:TypeScript,level:proficient,color:#00B578},{name:Stage 模型,level:proficient,color:#00B578},{name:Grid 布局,level:proficient,color:#00B578},{name:Navigation,level:familiar,color:#FF7A00},{name:HTTP 请求,level:familiar,color:#FF7A00},{name:状态管理,level:expert,color:#0A59F7},]getAlignDesc():string{constoptthis.alignOptions.find(oo.valuethis.currentAlign)returnopt?.desc??}build(){Column(){Text(alignContent 交互演示).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#1A1A1A).padding({left:24,top:20,bottom:4}).alignSelf(ItemAlign.Start)Scroll(){Column({space:20}){// ── 控制面板 ──this.buildControlPanel()// ── 演示区 ──this.buildDemoArea()// ── 说明卡 ──if(this.showExplain){this.buildExplainCard()}// ── 实际应用技能墙 ──this.buildSkillWall()}.padding({left:16,right:16,bottom:24}).alignItems(HorizontalAlign.Start)}.layoutWeight(1).scrollBar(BarState.Auto)}.width(100%).height(100%).backgroundColor(#F5F6F8)}// ── 控制面板 ──BuilderbuildControlPanel(){Column({space:12}){Text(选择 alignContent 值).fontSize(14).fontColor(#1A1A1A).fontWeight(FontWeight.Bold)Flex({wrap:FlexWrap.Wrap}){ForEach(this.alignOptions,(opt:alignOptionsParams){Text(opt.label).fontSize(13).fontColor(this.currentAlignopt.value?#FFFFFF:#555555).backgroundColor(this.currentAlignopt.value?#0A59F7:#F0F0F0).padding({left:14,right:14,top:6,bottom:6}).borderRadius(20).margin({right:8,bottom:8}).onClick((){this.currentAlignopt.value})})}// 容器高度调节Row({space:12}){Text(容器高度:).fontSize(13).fontColor(#666666).width(70)Slider({value:this.containerHeight,min:150,max:500,step:10}).layoutWeight(1).onChange((val:number){this.containerHeightMath.round(val)})Text(${this.containerHeight}vp).fontSize(13).fontColor(#0A59F7).width(60)}// 当前效果描述Row({space:6}){Text(效果).fontSize(13).fontColor(#888888)Text(this.getAlignDesc()).fontSize(13).fontColor(#1A1A1A)}}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%).alignItems(HorizontalAlign.Start)}// ── 演示区 ──BuilderbuildDemoArea(){Column({space:8}){Row(){Text(实时预览).fontSize(14).fontColor(#1A1A1A).fontWeight(FontWeight.Bold)Blank()Text(alignContent: (this.alignOptions.find(oo.valuethis.currentAlign)?.label??)).fontSize(12).fontColor(#0A59F7).fontFamily(monospace)}.width(100%)// 演示容器有明确高度超过内容高度才能看到 alignContent 效果Flex({wrap:FlexWrap.Wrap,alignContent:this.currentAlign// 关键alignContent 由状态控制}){ForEach([ArkTS,ArkUI,Layout,Flex,Grid,Nav,State,HTTP],(tag:string){Text(tag).fontSize(13).fontColor(#0A59F7).backgroundColor(#EBF2FF).padding({left:12,right:12,top:6,bottom:6}).borderRadius(20).margin({right:8,bottom:8})})}.width(100%).height(this.containerHeight)// 高度可调超过内容才有效果.backgroundColor(#F8F8F8).border({width:1,color:#DDDDDD,radius:8}).padding(8).animation({duration:300,curve:Curve.EaseInOut})}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%)}// ── 说明卡 ──BuilderbuildExplainCard(){Column({space:8}){Row(){Text(⚠️ 生效前提).fontSize(14).fontColor(#FF7A00).fontWeight(FontWeight.Bold)Blank()Text(收起).fontSize(12).fontColor(#AAAAAA).onClick((){this.showExplainfalse})}.width(100%)Column({space:6}){Text(1. 父容器必须设置 wrap: FlexWrap.Wrap开启换行).fontSize(13).fontColor(#555555)Text(2. 容器必须有明确的高度且大于内容总高度).fontSize(13).fontColor(#555555)Text(3. 内容必须真的换了行只有一行时 alignContent 无效).fontSize(13).fontColor(#555555)Text(alignContent 控制的是多行整体的分布单行场景用 justifyContent 和 alignItems 即可).fontSize(12).fontColor(#AAAAAA).lineHeight(18)}}.padding(16).backgroundColor(#FFF8EE).borderRadius(12).border({width:1,color:#FFE0A8}).width(100%).alignItems(HorizontalAlign.Start)}// ── 实际应用技能墙 ──BuilderbuildSkillWall(){Column({space:12}){Text(实际应用开发者技能墙).fontSize(15).fontWeight(FontWeight.Bold).fontColor(#1A1A1A)Flex({wrap:FlexWrap.Wrap,alignContent:FlexAlign.Start}){ForEach(this.skills,(skill:Skill){this.buildSkillBadge(skill)})}.width(100%)}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%).alignItems(HorizontalAlign.Start)}// ── 技能徽章 ──BuilderbuildSkillBadge(skill:Skill){Row({space:6}){Column().width(8).height(8).backgroundColor(skill.color).borderRadius(4)Text(skill.name).fontSize(13).fontColor(skill.color).fontWeight(FontWeight.Medium)Text(skill.levelexpert?精通:skill.levelproficient?熟练:了解).fontSize(10).fontColor(#AAAAAA)}.padding({left:12,right:12,top:6,bottom:6}).backgroundColor(${skill.color}15).border({width:1,color:${skill.color}40,radius:20}).margin({right:8,bottom:8})}}alignContent 的生效条件这个属性有两个前提缺一不可父容器必须开启换行wrap: FlexWrap.Wrap容器有多余高度容器高度大于内容实际高度才有分布的空间如果只有一行内容alignContent没有效果用alignItems代替。小结alignContent是 Flex 布局里处理多行整体分布的属性在 PC 端页面空间充裕的场景里非常有用。记住使用前提换行FlexWrap.Wrap 有多余高度。两个条件都满足再根据视觉需求选择合适的分布方式。
HarmonyOS PC 应用 Flex alignContent 详解——多行内容的整体分布控制
发布时间:2026/6/14 7:25:06
文章目录alignItems 和 alignContent 的区别alignContent 的取值完整 DemoalignContent 的生效条件小结alignItems 和 alignContent 的区别学 Flex 的时候这两个属性特别容易搞混。alignItems控制每行内各子项在交叉轴上的对齐方式居中/顶部/底部。alignContent控制多行整体在容器交叉轴上的分布方式只有在容器开启了FlexWrap.Wrap换行并且高度大于实际内容高度时才生效。打个比方一排书架alignItems控制每本书放多高多排书架alignContent控制多排书架在整个书柜里如何分布——靠上、靠下、均匀分布还是中间集中。在 PC 端可用空间比手机端大很多多行内容在高度方向上的分布就更加重要。alignContent在 PC 端应用里的使用场景比手机端更多。alignContent 的取值// 在 Flex 容器上设置需要 wrap: FlexWrap.WrapFlex({wrap:FlexWrap.Wrap,alignContent:FlexAlign.Start}){...}取值效果FlexAlign.Start多行集中在交叉轴起始端默认FlexAlign.Center多行集中在交叉轴中间FlexAlign.End多行集中在交叉轴末端FlexAlign.SpaceBetween多行两端对齐中间均匀分布FlexAlign.SpaceAround每行两侧等距首尾有半格间距FlexAlign.SpaceEvenly所有间距包括首尾均等完整 Demo新建文件PcAlignContentPage.etsinterfaceSkill{name:stringlevel:string// expert | proficient | familiarcolor:string}interfacealignOptionsParams{label:string,value:FlexAlign,desc:string}EntryComponentstruct PcAlignContentPage{StatecurrentAlign:FlexAlignFlexAlign.StartStatecontainerHeight:number300StateshowExplain:booleantrueprivatealignOptions:alignOptionsParams[][{label:Start,value:FlexAlign.Start,desc:多行从顶部开始向下排列底部留空},{label:Center,value:FlexAlign.Center,desc:多行整体居中上下等距留空},{label:End,value:FlexAlign.End,desc:多行集中在底部顶部留空},{label:SpaceBetween,value:FlexAlign.SpaceBetween,desc:首行和末行贴边中间均匀分布},{label:SpaceAround,value:FlexAlign.SpaceAround,desc:每行两侧等距首尾有半格间距},{label:SpaceEvenly,value:FlexAlign.SpaceEvenly,desc:包括首尾在内所有间距完全相等},]privateskills:Skill[][{name:ArkTS,level:expert,color:#0A59F7},{name:ArkUI,level:expert,color:#0A59F7},{name:HarmonyOS PC,level:proficient,color:#00B578},{name:Flex 布局,level:expert,color:#0A59F7},{name:TypeScript,level:proficient,color:#00B578},{name:Stage 模型,level:proficient,color:#00B578},{name:Grid 布局,level:proficient,color:#00B578},{name:Navigation,level:familiar,color:#FF7A00},{name:HTTP 请求,level:familiar,color:#FF7A00},{name:状态管理,level:expert,color:#0A59F7},]getAlignDesc():string{constoptthis.alignOptions.find(oo.valuethis.currentAlign)returnopt?.desc??}build(){Column(){Text(alignContent 交互演示).fontSize(18).fontWeight(FontWeight.Bold).fontColor(#1A1A1A).padding({left:24,top:20,bottom:4}).alignSelf(ItemAlign.Start)Scroll(){Column({space:20}){// ── 控制面板 ──this.buildControlPanel()// ── 演示区 ──this.buildDemoArea()// ── 说明卡 ──if(this.showExplain){this.buildExplainCard()}// ── 实际应用技能墙 ──this.buildSkillWall()}.padding({left:16,right:16,bottom:24}).alignItems(HorizontalAlign.Start)}.layoutWeight(1).scrollBar(BarState.Auto)}.width(100%).height(100%).backgroundColor(#F5F6F8)}// ── 控制面板 ──BuilderbuildControlPanel(){Column({space:12}){Text(选择 alignContent 值).fontSize(14).fontColor(#1A1A1A).fontWeight(FontWeight.Bold)Flex({wrap:FlexWrap.Wrap}){ForEach(this.alignOptions,(opt:alignOptionsParams){Text(opt.label).fontSize(13).fontColor(this.currentAlignopt.value?#FFFFFF:#555555).backgroundColor(this.currentAlignopt.value?#0A59F7:#F0F0F0).padding({left:14,right:14,top:6,bottom:6}).borderRadius(20).margin({right:8,bottom:8}).onClick((){this.currentAlignopt.value})})}// 容器高度调节Row({space:12}){Text(容器高度:).fontSize(13).fontColor(#666666).width(70)Slider({value:this.containerHeight,min:150,max:500,step:10}).layoutWeight(1).onChange((val:number){this.containerHeightMath.round(val)})Text(${this.containerHeight}vp).fontSize(13).fontColor(#0A59F7).width(60)}// 当前效果描述Row({space:6}){Text(效果).fontSize(13).fontColor(#888888)Text(this.getAlignDesc()).fontSize(13).fontColor(#1A1A1A)}}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%).alignItems(HorizontalAlign.Start)}// ── 演示区 ──BuilderbuildDemoArea(){Column({space:8}){Row(){Text(实时预览).fontSize(14).fontColor(#1A1A1A).fontWeight(FontWeight.Bold)Blank()Text(alignContent: (this.alignOptions.find(oo.valuethis.currentAlign)?.label??)).fontSize(12).fontColor(#0A59F7).fontFamily(monospace)}.width(100%)// 演示容器有明确高度超过内容高度才能看到 alignContent 效果Flex({wrap:FlexWrap.Wrap,alignContent:this.currentAlign// 关键alignContent 由状态控制}){ForEach([ArkTS,ArkUI,Layout,Flex,Grid,Nav,State,HTTP],(tag:string){Text(tag).fontSize(13).fontColor(#0A59F7).backgroundColor(#EBF2FF).padding({left:12,right:12,top:6,bottom:6}).borderRadius(20).margin({right:8,bottom:8})})}.width(100%).height(this.containerHeight)// 高度可调超过内容才有效果.backgroundColor(#F8F8F8).border({width:1,color:#DDDDDD,radius:8}).padding(8).animation({duration:300,curve:Curve.EaseInOut})}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%)}// ── 说明卡 ──BuilderbuildExplainCard(){Column({space:8}){Row(){Text(⚠️ 生效前提).fontSize(14).fontColor(#FF7A00).fontWeight(FontWeight.Bold)Blank()Text(收起).fontSize(12).fontColor(#AAAAAA).onClick((){this.showExplainfalse})}.width(100%)Column({space:6}){Text(1. 父容器必须设置 wrap: FlexWrap.Wrap开启换行).fontSize(13).fontColor(#555555)Text(2. 容器必须有明确的高度且大于内容总高度).fontSize(13).fontColor(#555555)Text(3. 内容必须真的换了行只有一行时 alignContent 无效).fontSize(13).fontColor(#555555)Text(alignContent 控制的是多行整体的分布单行场景用 justifyContent 和 alignItems 即可).fontSize(12).fontColor(#AAAAAA).lineHeight(18)}}.padding(16).backgroundColor(#FFF8EE).borderRadius(12).border({width:1,color:#FFE0A8}).width(100%).alignItems(HorizontalAlign.Start)}// ── 实际应用技能墙 ──BuilderbuildSkillWall(){Column({space:12}){Text(实际应用开发者技能墙).fontSize(15).fontWeight(FontWeight.Bold).fontColor(#1A1A1A)Flex({wrap:FlexWrap.Wrap,alignContent:FlexAlign.Start}){ForEach(this.skills,(skill:Skill){this.buildSkillBadge(skill)})}.width(100%)}.padding(16).backgroundColor(#FFFFFF).borderRadius(12).width(100%).alignItems(HorizontalAlign.Start)}// ── 技能徽章 ──BuilderbuildSkillBadge(skill:Skill){Row({space:6}){Column().width(8).height(8).backgroundColor(skill.color).borderRadius(4)Text(skill.name).fontSize(13).fontColor(skill.color).fontWeight(FontWeight.Medium)Text(skill.levelexpert?精通:skill.levelproficient?熟练:了解).fontSize(10).fontColor(#AAAAAA)}.padding({left:12,right:12,top:6,bottom:6}).backgroundColor(${skill.color}15).border({width:1,color:${skill.color}40,radius:20}).margin({right:8,bottom:8})}}alignContent 的生效条件这个属性有两个前提缺一不可父容器必须开启换行wrap: FlexWrap.Wrap容器有多余高度容器高度大于内容实际高度才有分布的空间如果只有一行内容alignContent没有效果用alignItems代替。小结alignContent是 Flex 布局里处理多行整体分布的属性在 PC 端页面空间充裕的场景里非常有用。记住使用前提换行FlexWrap.Wrap 有多余高度。两个条件都满足再根据视觉需求选择合适的分布方式。