
文章目录前言Flex 到底比 Row 强在哪代码实现卡片怎么自适应宽度核心代码踩坑为什么我的 Flex 没换行一个完整的响应式例子常见误区小白必踩完整可运行示例响应式卡片完整示例写在最后前言前面讲了 Column 和 Row都是死布局——几个元素就占几份空间。但真实项目里你经常会碰到这种需求一行想放尽量多的卡片屏幕宽就多放几个窄就少放几个还不许重叠。这种能屈能伸的活儿就得靠Flex弹性布局。这篇文章我用一个商品卡片墙的例子带你把 Flex 的几个核心参数吃透顺便聊聊它和 Row 到底差在哪。Flex 到底比 Row 强在哪先说结论Flex 是 Row/Column 的完全体。Row 只能横排且不能换行Flex 可以横排也可以竖排、还能自动换行。关键就在Flex({ direction, wrap, justifyContent, alignItems })这几个参数。代码实现Flex({direction:FlexDirection.Row,// 主轴方向横wrap:FlexWrap.Wrap,// 放不下就换行justifyContent:FlexAlign.SpaceBetween,// 主轴均匀分布alignItems:ItemAlign.Center// 交叉轴居中}){ForEach(this.cards,(item){this.CardItem(item)})}.width(100%).padding(12)逐行看direction: FlexDirection.Row主轴是横向子项从左到右排。wrap: FlexWrap.Wrap这是 Flex 的精髓。设了Wrap一行塞满就自动换下一行不会像 Row 那样超出屏幕。justifyContent: FlexAlign.SpaceBetween主轴方向上首尾贴边、中间均匀留白。alignItems: ItemAlign.Center换行后每一行内部垂直居中。SpaceBetween、SpaceAround、SpaceEvenly是三个最容易混的。Between是两端贴边中间均分Around是每个元素左右都留一半空隙Evenly是所有空隙完全相等。想要哪种你试一下就懂了。卡片怎么自适应宽度光换行还不够我们希望每张卡片宽度能跟着屏幕变。这里要用.layoutWeight()或者固定百分比宽度。核心代码BuilderCardItem(item:Product){Column(){Image(item.img).width(100%).height(100).borderRadius(8)Text(item.name).fontSize(14).margin({top:8})Text(¥item.price).fontSize(16).fontColor(#FF4500).fontWeight(FontWeight.Bold)}.width(48%)// 一行两张留点间隙.backgroundColor(#FFFFFF).borderRadius(12).padding(10).shadow({radius:6,color:#00000010})}说明几点.width(48%)每张卡占父容器 48% 宽两张加起来 96%剩下 4% 当间隙正好一行两张。手机横过来变宽了48% 也会跟着变大天然响应式。.shadow(...)加一点投影卡片立刻有浮起来的质感参数里color: #00000010是带透明度的黑。用Builder把卡片抽成一个可复用函数ForEach 里直接调用代码清爽很多。踩坑为什么我的 Flex 没换行我第一次用 Flex 就栽在这。当时写的是Flex({ wrap: FlexWrap.Wrap })但子项宽度写成了固定120屏幕能塞 5 个结果它真就塞了 5 个——因为 5×120 没超屏宽当然不换行。要点换行的前提是一行放不下。如果你的子项宽度是百分比如 48%那永远一行两张如果子项是固定值就要算好数量。想要按屏幕宽度自动决定几个就得配合layoutWeight或百分比。一个完整的响应式例子EntryComponentV2struct ProductWall{Localcards:Product[][/* 假设有 10 条数据 */]build(){Scroll(){Flex({wrap:FlexWrap.Wrap,justifyContent:FlexAlign.SpaceBetween}){ForEach(this.cards,(item:Product){this.CardItem(item)},(item:Product)item.id)}.padding(12)}.width(100%).height(100%)}}注意外层我包了一个Scroll()。因为卡片换行后内容会变高超出一屏就得能滚动否则下面的卡片你看不到。这是新手最容易漏的一步。常见误区小白必踩误区说明忘了wrap: FlexWrap.WrapFlex 默认不换行一行放不下就溢出屏幕而不是自动换到下一行。以为fr是固定像素1fr 1fr 1fr是三等分剩余空间不是三个固定宽。屏幕变宽格子跟着变这正是响应式的妙处。换行后不包Scroll卡片换行变高超出一屏看不到记得外层套Scroll才能滚动。下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲改一改文末「动手改一改」里的参数亲眼看看效果。完整可运行示例响应式卡片这个例子用 Flex 做一个「宽度不够就换行」的标签卡片窗口拉宽拉窄都不会挤爆。完整示例// 用 Flex 的 wrap 实现自动换行标签墙EntryComponentstruct TagWall{privatetags:string[][HarmonyOS7,ArkTS,声明式,动画,分布式,性能,组件化,深色模式]build(){Flex({wrap:FlexWrap.Wrap,spacing:10,alignItems:ItemAlign.Center}){ForEach(this.tags,(t:string){Text(t).padding({left:14,right:14,top:6,bottom:6}).backgroundColor(#E8F0FE).fontColor(#007DFF).borderRadius(16)// 圆角胶囊样式})}.width(100%).padding(16)}}你会看到什么一行排满标签后自动换到下一行标签之间横向、纵向都有 10vp 空隙整体像一块「胶囊墙」。把手机横过来或拖动 Previewer 宽度标签会重新流式排布。动手改一改把FlexWrap.Wrap改成FlexWrap.NoWrap再缩短容器宽度观察标签被压缩而非换行。给Flex加.justifyContent(FlexAlign.SpaceBetween)看每行剩余空间如何分配。把borderRadius(16)改成borderRadius(4)感受圆角大小对观感的影响。写在最后Flex 的精髓就一句话方向 换行 对齐三件套。记住wrap: FlexWrap.Wrap是它能屈能伸的根本原因。下回做商品列表、标签墙、九宫格先想 Flex别再傻傻地用 Row 硬撑了。建议你把上面例子里的48%改成31%跑一下看看一行是不是变成三张——这种小实验最能帮你建立响应式的直觉。