欢迎光临
我们一直在努力

HarmonyOS6 flexShrink 实战:订单卡片里的长文本到底该让谁让位

文章目录

    • 先决定谁不能被压缩
    • 直接看实现
    • flexShrink 不是越小越好
    • 标签行为什么要 clip

列表卡片里最怕遇到长文本。

订单号很长,商品名更长,右侧还要放状态、金额、时间。空间不够时,如果每个元素都想保住自己的宽度,最后页面一定会挤成一团。flexShrink 解决的就是这个问题:当主轴空间不足时,谁可以收缩,谁不能收缩。

flexShrink 空间不足时的收缩示意图

先决定谁不能被压缩

订单卡片里有些信息不能被压缩:

  • 订单状态,比如“待支付”“配送中”;
  • 金额,比如 ¥4,888.00;

订单卡片信息优先级示意图

  • 操作按钮或关键标签。

这些信息一旦被压缩,用户就很难判断订单状态。相反,商品名、订单号这类长文本可以截断展示,完整内容可以放到详情页。

订单卡片信息优先级示意图

所以这里的核心策略是:重要短信息 flexShrink(0),长文本 flexShrink(1) 并配合省略号。

直接看实现

下面同时放了概念行和真实订单卡片两种写法。

/**
* Flex flexShrink:弹性收缩的卡片标签行
* 知识点:flexShrink 控制子项在空间不足时的收缩比例
*/

interface OrderCardInfo {
orderId: string
productName: string
statusLabel: string
statusColor: string
statusBg: string
amount: string
date: string
tags: string[]
}

@Entry
@Component
struct FlexShrinkOrderPage {
@State shrinkMode: number = 0

private orders: OrderCardInfo[] = [
{
orderId: 'NO.20240601001',
productName: 'HarmonyOS 开发者套件 旗舰版超长名称款',
statusLabel: '待支付',
statusColor: '#FF8C00',
statusBg: '#FFF8E8',
amount: '¥1,299.00',
date: '2024-06-01 14:32',
tags: ['包邮', '7天退换', '正品保障', '极速发货', '官方认证']
},
{
orderId: 'NO.20240530002',
productName: '华为MatePad Pro 平板电脑',
statusLabel: '配送中',
statusColor: '#007DFF',
statusBg: '#EAF3FF',
amount: '¥4,888.00',
date: '2024-05-30 09:15',
tags: ['顺丰', '已签收确认', '开具发票']
},
{
orderId: 'NO.20240528003',
productName: '智能手表 SE2 碳晶灰',
statusLabel: '已完成',
statusColor: '#07C160',
statusBg: '#EDFAF4',
amount: '¥1,099.00',
date: '2024-05-28 18:20',
tags: ['好评', '返现']
},
]

@Builder
ShrinkDemo(title: string, desc: string) {
Column({ space: 6 }) {
Text(title).fontSize(13).fontWeight(FontWeight.Medium).fontColor('#1A1A1A')
Text(desc).fontSize(11).fontColor('#999999')
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Text('不收缩')
.fontSize(13)
.fontColor('#FFFFFF')
.backgroundColor('#FF4D4D')
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
.borderRadius(6)
.flexShrink(0)

Text('这段文字会在空间不足时被压缩,体现flexShrink效果')
.fontSize(13)
.fontColor('#1A1A1A')
.backgroundColor('#E8F3FF')
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
.borderRadius(6)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.flexShrink(1)
.margin({ left: 8 })

Text('操作')
.fontSize(13)
.fontColor('#007DFF')
.backgroundColor('#EAF3FF')
.padding({ left: 10, right: 10, top: 6, bottom: 6 })
.borderRadius(6)
.flexShrink(0)
.margin({ left: 8 })
}
.width('100%')
.backgroundColor('#F5F5F5')
.padding(10)
.borderRadius(8)
}
}

build() {
Column() {
Text('flexShrink 弹性收缩')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.padding({ left: 16, right: 16, top: 20, bottom: 4 })
.alignSelf(ItemAlign.Start)

Text('控制子项在主轴空间不足时的收缩比例(0=不收缩,1=按比例收缩)')
.fontSize(13)
.fontColor('#888888')
.padding({ left: 16, right: 16, bottom: 16 })
.alignSelf(ItemAlign.Start)

Column({ space: 16 }) {
this.ShrinkDemo(
'flexShrink:0 不收缩',
'红色和蓝色区域 flexShrink=0,中间文字 flexShrink=1 会被压缩'
)
}
.padding({ left: 16, right: 16 })
.width('100%')

Divider().color('#EEEEEE').margin({ top: 16, bottom: 8 })

Text('实际应用:订单列表标签行')
.fontSize(15)
.fontWeight(FontWeight.Medium)
.fontColor('#1A1A1A')
.padding({ left: 16, right: 16, top: 8, bottom: 12 })
.alignSelf(ItemAlign.Start)

Column({ space: 12 }) {
ForEach(this.orders, (order: OrderCardInfo) => {
Column({ space: 12 }) {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Text('订单号 ' + order.orderId)
.fontSize(12)
.fontColor('#999999')
.flexShrink(1)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })

Text(order.statusLabel)
.fontSize(13)
.fontWeight(FontWeight.Medium)
.fontColor(order.statusColor)
.backgroundColor(order.statusBg)
.padding({ left: 8, right: 8, top: 4, bottom: 4 })
.borderRadius(6)
.flexShrink(0)
.margin({ left: 8 })
}
.width('100%')

Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.End }) {
Text(order.productName)
.fontSize(15)
.fontColor('#1A1A1A')
.fontWeight(FontWeight.Medium)
.flexShrink(1)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.layoutWeight(1)

Column({ space: 2 }) {
Text(order.amount)
.fontSize(17)
.fontWeight(FontWeight.Bold)
.fontColor('#FF4D4D')
Text(order.date)
.fontSize(11)
.fontColor('#BBBBBB')
}
.alignItems(HorizontalAlign.End)
.flexShrink(0)
.margin({ left: 12 })
}
.width('100%')

Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
ForEach(order.tags, (tag: string) => {
Text(tag)
.fontSize(11)
.fontColor('#888888')
.backgroundColor('#F5F5F5')
.padding({ left: 6, right: 6, top: 3, bottom: 3 })
.borderRadius(4)
.flexShrink(0)
.margin({ right: 6 })
})
}
.width('100%')
.clip(true)
}
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(14)
.shadow({ radius: 6, color: '#10000000', offsetX: 0, offsetY: 2 })
})
}
.padding({ left: 16, right: 16 })
.width('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F6FA')
}
}

订单卡片运行效果图

flexShrink 不是越小越好

很多人看到 flexShrink(0) 能防止压缩,就到处加。这个习惯不太好。

如果所有元素都不允许收缩,空间不够时只能溢出。正确做法是给元素分级:关键操作、状态、金额不收缩;描述类文本可以收缩,并配合 maxLines 和 textOverflow 做截断。

这样页面不会乱,信息优先级也更清楚。

标签行为什么要 clip

第三行标签全部设置了 flexShrink(0),意思是每个标签保持自己的可读性,不硬压缩成奇怪的形状。

订单标签裁剪策略示意图

但标签太多时,肯定会超过一行宽度。所以外层加了 .clip(true)

赞(0)
未经允许不得转载:171主机测评 » HarmonyOS6 flexShrink 实战:订单卡片里的长文本到底该让谁让位
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址