小雨同学 2026-05-12 08:22:06 发布前言
Pura X Max 的外屏并不小,但它仍然属于折叠态下的窄窗口场景。列表页如果把标题、摘要、时间、来源、标签、状态、按钮全都塞进一张卡片,外屏很快就会变得拥挤。用户真正想先看到的是这条记录是什么、当前处于什么状态、能不能马上处理,其他信息可以等到空间足够时再展示。
Pura X Max 的外屏为 5.4 英寸,内屏为 7.7 英寸,外屏分辨率为 1848 × 1264,内屏分辨率为 2584 × 1828,系统版本为 HarmonyOS 6.1。外屏和内屏的尺寸差异很明显,同一张卡片在两种形态下不应该展示完全相同的信息量。
我在处理这类页面时,会先把业务数据拆成两层:核心信息和扩展信息。折叠态只保留核心信息,展开态再展示扩展信息。这样做之后,外屏不会因为字段太多而显得挤,展开态也不会因为信息太少而显得空。

问题出在字段没有分层
很多卡片一开始会把所有字段都展示出来。比如一条整理记录,可能包含这些内容:
标题。
状态。
来源。
时间。
标签。
摘要。
优先级。
操作按钮。
这些字段都重要,但它们的重要性并不一样。
外屏空间有限时,标题和状态的优先级最高。标题让用户知道这条记录是什么,状态让用户知道是否需要处理,主操作按钮让用户可以继续下一步。摘要、来源、时间、标签这些信息虽然有价值,但它们不一定要在折叠态里全部出现。
如果卡片没有信息层级,折叠态会出现几个问题。
卡片高度变大,一屏能看到的记录变少。
摘要占据太多空间,标题反而不突出。
标签、来源、时间同时出现,视觉噪声变多。
主操作按钮被挤到卡片底部,点击路径变长。
折叠态页面更适合快速浏览。用户先扫一遍标题和状态,再决定是否进入处理。展开态有更大的显示空间,可以把摘要、来源、时间、标签展示出来,帮助用户减少点击和跳转。
把同一条数据拆成两层
信息密度控制的关键,是在 UI 层明确区分核心信息和扩展信息。
核心信息放在 compact 状态下:
titlestatusprimaryAction扩展信息放在 expanded 状态下:
summarysourcetimetagpriority这不是简单隐藏几个字段。字段分层之后,页面的阅读路径会更清楚。外屏下,用户只需要扫标题和状态;展开态下,用户可以在不进入详情的情况下看到更多上下文。
响应式布局本身强调根据屏幕尺寸和窗口变化调整页面结构,让不同设备和不同窗口尺寸下的阅读、交互体验保持稳定。Pura X Max 这种外屏和内屏差异明显的设备,尤其适合用断点控制字段显示。
我这里仍然使用窗口宽度做判断。页面宽度低于 720vp 时进入 compact,只显示核心信息;达到 720vp 后进入 expanded,显示更多字段。
private readonly expandedWidth: number = 720;private isExpanded(): boolean { return this.pageWidth >= this.expandedWidth;}真实项目里可以继续细分,例如 compact、medium、expanded 三档。外屏只显示标题和状态,普通平板显示标题、状态和时间,Pura X Max 展开态显示摘要和标签。为了让问题聚焦,这里先保留两档。
用一个页面验证信息密度变化
下面的页面模拟了一组信息整理记录。窄窗口下,卡片只展示标题、状态和处理按钮;窗口变宽后,摘要、来源、时间、标签和优先级会一起出现。这样可以比较直观看到同一组数据在折叠态和展开态下的信息差异。
页面可以放到 entry/src/main/ets/pages/Index.ets 运行。Pura X Max 适配调试可以使用 DevEco Studio 6.1.0,并安装 Pura X Max 模拟器验证外屏和展开态效果。
interface InfoCardData { id: number; title: string; status: string; actionText: string; summary: string; source: string; time: string; tag: string; priority: string;}@Entry@Componentstruct Index { @State private pageWidth: number = 0; @State private selectedId: number = 1; private readonly expandedWidth: number = 720; private readonly cards: InfoCardData[] = [ { id: 1, title: '社区物业缴费提醒', status: '待处理', actionText: '处理', summary: '识别到物业费缴纳截止日期、金额明细和办理地点,建议添加提醒。', source: '拍照整理', time: '09:20', tag: '通知', priority: '高优先级' }, { id: 2, title: 'Pura X Max 适配会议纪要', status: '待确认', actionText: '确认', summary: '整理出外屏、展开态、横屏和悬停态几类页面问题,适合作为后续开发清单。', source: '语音转写', time: '10:45', tag: '会议', priority: '中优先级' }, { id: 3, title: '活动报名确认单', status: '已保存', actionText: '查看', summary: '提取到报名人、联系电话、活动时间和签到地址,后续可以加入日程。', source: '相册导入', time: '11:30', tag: '表单', priority: '普通' }, { id: 4, title: '客户需求变更记录', status: '待处理', actionText: '处理', summary: '本次变更涉及首页布局、权限配置、消息提醒和后台字段展示,需要同步给开发。', source: '文本整理', time: '13:10', tag: '项目', priority: '高优先级' }, { id: 5, title: '课程作业提交说明', status: '已整理', actionText: '查看', summary: '识别到提交时间、文件格式、命名规范和邮箱地址,适合保存为待办。', source: '拍照整理', time: '15:25', tag: '学习', priority: '普通' }, { id: 6, title: '门诊复查预约提示', status: '已保存', actionText: '查看', summary: '提取到复查时间、科室、楼层和注意事项,可以作为健康提醒保存。', source: '相册导入', time: '16:40', tag: '提醒', priority: '中优先级' } ]; private isExpanded(): boolean { return this.pageWidth >= this.expandedWidth; } private getColumnsTemplate(): string { return this.isExpanded() ? '1fr 1fr' : '1fr'; } private getPagePadding(): number { return this.isExpanded() ? 24 : 16; } private getHeaderTitle(): string { return this.isExpanded() ? '展开态显示完整上下文' : '折叠态保留核心信息'; } private getHeaderDesc(): string { if (this.isExpanded()) { return '摘要、来源、时间、标签和优先级已经展开,适合在大屏上快速判断记录内容。'; } return '当前只保留标题、状态和主操作,减少外屏卡片里的字段堆叠。'; } private getStatusColor(status: string): string { if (status === '待处理') { return '#B25E00'; } if (status === '待确认') { return '#7C3AED'; } return '#276749'; } private getStatusBgColor(status: string): string { if (status === '待处理') { return '#FFF4E5'; } if (status === '待确认') { return '#F1EAFE'; } return '#E7F5EE'; } @Builder private MetaPill(text: string) { Text(text) .fontSize(12) .fontColor('#4B5563') .padding({ left: 8, right: 8, top: 4, bottom: 4 }) .backgroundColor('#F3F4F6') .borderRadius(999) } @Builder private InfoCard(item: InfoCardData) { Column({ space: 12 }) { Row({ space: 10 }) { Column({ space: 8 }) { Text(item.title) .fontSize(this.isExpanded() ? 18 : 17) .fontWeight(FontWeight.Medium) .fontColor('#111827') .maxLines(this.isExpanded() ? 1 : 2) .textOverflow({ overflow: TextOverflow.Ellipsis }) Row({ space: 8 }) { Text(item.status) .fontSize(12) .fontColor(this.getStatusColor(item.status)) .padding({ left: 8, right: 8, top: 4, bottom: 4 }) .backgroundColor(this.getStatusBgColor(item.status)) .borderRadius(999) if (!this.isExpanded()) { Text('核心信息') .fontSize(12) .fontColor('#6B7280') } } } .layoutWeight(1) Button(item.actionText) .fontSize(13) .fontColor('#FFFFFF') .height(32) .padding({ left: 12, right: 12 }) .backgroundColor('#2F8F83') .borderRadius(16) .onClick(() => { this.selectedId = item.id; }) } .width('100%') .alignItems(VerticalAlign.Top) if (this.isExpanded()) { Text(item.summary) .fontSize(14) .fontColor('#4B5563') .lineHeight(20) .maxLines(2) .textOverflow({ overflow: TextOverflow.Ellipsis }) Row({ space: 8 }) { this.MetaPill(item.source) this.MetaPill(item.time) this.MetaPill(item.tag) this.MetaPill(item.priority) } .width('100%') } } .width('100%') .padding(this.isExpanded() ? 18 : 16) .backgroundColor(this.selectedId === item.id ? '#EEF7F5' : '#FFFFFF') .borderRadius(20) .border({ width: this.selectedId === item.id ? 1.5 : 1, color: this.selectedId === item.id ? '#2F8F83' : '#E5E7EB' }) .shadow({ radius: this.selectedId === item.id ? 12 : 8, color: '#12000000', offsetX: 0, offsetY: 4 }) } build() { Column({ space: 16 }) { Column({ space: 8 }) { Row() { Column({ space: 4 }) { Text('信息密度控制') .fontSize(this.isExpanded() ? 28 : 23) .fontWeight(FontWeight.Bold) .fontColor('#111827') Text(this.getHeaderTitle()) .fontSize(15) .fontColor('#2F8F83') } .layoutWeight(1) Text(Math.round(this.pageWidth).toString() + 'vp') .fontSize(13) .fontColor('#374151') .padding({ left: 10, right: 10, top: 6, bottom: 6 }) .backgroundColor('#FFFFFF') .borderRadius(999) } .width('100%') Text(this.getHeaderDesc()) .fontSize(14) .fontColor('#6B7280') .lineHeight(21) } .width('100%') .padding({ left: this.getPagePadding(), right: this.getPagePadding(), top: 18 }) Scroll() { Grid() { ForEach(this.cards, (item: InfoCardData) => { GridItem() { this.InfoCard(item) } }, (item: InfoCardData) => item.id.toString()) } .columnsTemplate(this.getColumnsTemplate()) .columnsGap(12) .rowsGap(12) .width('100%') .padding({ left: this.getPagePadding(), right: this.getPagePadding(), bottom: 24 }) } .layoutWeight(1) .width('100%') .edgeEffect(EdgeEffect.Spring) } .width('100%') .height('100%') .backgroundColor('#F6F7F9') .onAreaChange((_: Area, newValue: Area) => { const width = Number(newValue.width); if (!Number.isNaN(width) && width > 0) { this.pageWidth = width; } }) }}关键实现点和适配边界
这里的实现重点不在卡片样式,而在字段显示策略。
pageWidth 记录页面当前可用宽度,isExpanded() 判断是否进入展开态。页面根容器绑定 onAreaChange 后,窗口尺寸变化会更新 pageWidth。组件区域变化事件会在组件显示尺寸或位置变化时触发,适合用来处理这类页面级布局响应。
@State private pageWidth: number = 0;private isExpanded(): boolean { return this.pageWidth >= this.expandedWidth;}卡片里的核心信息一直显示。
Text(item.title)Text(item.status)Button(item.actionText)扩展信息只在 expanded 下显示。
if (this.isExpanded()) { Text(item.summary) Row({ space: 8 }) { this.MetaPill(item.source) this.MetaPill(item.time) this.MetaPill(item.tag) this.MetaPill(item.priority) }}这个判断看起来很简单,但它解决的是页面信息层级问题。外屏下,用户看到的是标题、状态、操作;展开态下,用户看到的是完整上下文。两种形态使用同一组数据,但 UI 呈现的信息量不同。
真实项目里可以把字段进一步分层。
核心信息适合包含标题、状态、主操作、异常提示。
扩展信息适合包含摘要、来源、时间、标签、优先级、关联对象。
详情信息适合放到详情页或展开面板里,比如完整原文、识别结果、操作日志、附件列表。
折叠态页面最怕字段堆叠。能在列表里隐藏的内容,就不要全部放到卡片上。用户需要快速判断时,字段越多,决策成本越高。
验证要看什么
这次适合截两张图。
第一张保留窄窗口状态。顶部显示 折叠态保留核心信息,卡片里只有标题、状态和按钮。这个状态下要重点看卡片高度是否克制,一屏能不能看到多条记录,按钮是否容易点击。

第二张保留展开态状态。顶部显示 展开态显示完整上下文,卡片里出现摘要、来源、时间、标签和优先级。这个状态下要重点看字段是否分组清楚,摘要是否影响列表扫描,双列卡片是否仍然保持足够留白。

如果外屏截图里一张卡片已经占了大半屏,说明字段收得还不够。如果展开态截图里卡片显得空,说明扩展信息没有把大屏价值体现出来。
总结
Pura X Max 折叠态页面的信息密度控制,核心是给字段分层。
外屏下保留标题、状态和主操作,可以让用户快速扫列表,不被摘要、标签、时间这些次级信息干扰。展开态再补充摘要、来源、时间、标签和优先级,可以减少进入详情的次数,也能让内屏空间发挥作用。
这个方法适合记录列表、通知列表、整理结果列表、任务列表、设置项列表等场景。真正落到项目里,不建议把字段简单按数量裁掉,而要按用户判断路径来排优先级。用户第一眼必须知道这是什么、现在是什么状态、能做什么;其他上下文,交给更宽的窗口展示。
相关推荐
鸿蒙小助手
111
0
244
0
IOS工程师转行
302
0
程序人生记录者
278
0
小雨同学
产品总监、独立开发者社群主理人、资深全栈工程师,HarmonyOS应用开发者高级认证,PMP认证,CSDN博客专家,鸿蒙极客,Trae Fellow,阿里云社区专家博主、51CTO 博客专家、OpenTiny 优秀布道师、科大讯飞荣誉讲师。
帖子
提问
粉丝
京公网安备:11010502051901号