标签:Harmony os、ArkTS、ArkUI、响应式布局、几何计算
同一张 70×70 图纸在拼豆制图里至少出现三次:编号页总览要看全局轮廓,展开页要读清每格色号,未来的内嵌图纸视口还要在有限高度里浏览。三种场景若共用一个格子尺寸,要么总览溢出,要么展开态字太小;若各处随手写常量,又会出现纸宽、坐标栏和点击热区互不一致。
本篇从overviewCellSize()、expandedCellSize()以及当前尚未接入渲染树的chartCellSize()出发,说明如何把格子尺寸、纸张宽度、表头高度和视口高度收拢为一份可审计的几何策略,并用 48、64 两个临界点防止响应式规则悄悄漂移。
一、三种场景其实是三种信息密度
总览态的目标是“认出图”,展开态的目标是“读出编号”,受限视口的目标是“在页面中可操作”。它们对格子尺寸的要求不同:
| 场景 | 70 列格子尺寸 | 70 列纸宽 | 色号策略 |
|---|---|---|---|
| 总览 | 4vp | 304vp | 默认不显示 |
| 展开 | 11vp | 804vp | 始终显示 |
| 受限视口策略 | 10vp | 726vp | 视用途显示 |
纸宽来自真实公式,而不是估算:
总览:24 + 70 × 4 = 304vp 展开:34 + 70 × 11 = 804vp 视口:26 + 70 × 10 = 726vp这三组前导宽度分别容纳行号、边距和边框。只改格子尺寸而不改纸宽函数,最容易造成最后一列裁切。
二、现有实现把断点写进三个函数
总览规则:
privateoverviewCellSize(pattern:Pattern):number{if(pattern.width>=64)return4;if(pattern.width>=48)return5;return8;}展开规则:
privateexpandedCellSize(pattern:Pattern):number{if(pattern.width>=64)return11;if(pattern.width>=48)return12;return14;}受限视口规则:
privatechartCellSize(pattern:Pattern):number{if(pattern.width>=64)return10;if(pattern.width>=48)return11;return10;}这里有一个值得警惕的事实:chartCellSize()、chartPaperWidth()和chartViewportHeight()当前只有定义,没有调用。它们可能是待接入能力,也可能是重构后遗留代码。继续修改之前,应先决定“接入”还是“删除”,不能把未使用函数当成已有页面行为。
三、临界点要按分段函数理解
判断顺序是>=64、>=48、其余,因此宽度 47、48、63、64 是最有价值的四个样本:
functionoverviewSize(width:number):number{if(width>=64)return4;if(width>=48)return5;return8;}// 期望:47→8,48→5,63→5,64→4若测试只使用 35 和 70,就算有人把>=64错写成>64,也不一定立刻发现。边界样本应同时覆盖临界点前一位和临界点本身。
还要明确规则依据的是pattern.width而非设备宽度。图纸越宽,单格越小;设备适配由页面最大宽度和滚动容器负责。这两个维度不要混进同一个 if 链。
四、纸宽与格子尺寸必须一次计算
当前渲染中多次调用overviewCellSize(pattern):表头、行标签高度、格子和纸宽都依赖它。函数是纯计算,所以结果一致;但维护者仍需逐处确认没有漏改。
可以把几何结果集中起来:
interfaceChartGeometry{cell:number;rowLabelWidth:number;headerHeight:number;paddingRight:number;paperWidth:number;}functionoverviewGeometry(width:number):ChartGeometry{constcell=width>=64?4:width>=48?5:8;constrowLabelWidth=18;constpaddingRight=6;return{cell,rowLabelWidth,headerHeight:16,paddingRight,paperWidth:rowLabelWidth+width*cell+paddingRight};}页面在一次构建中取一个对象,表头和主体共享同一结果。这样“格子改成 5vp、纸宽仍按 4vp 算”的错误从结构上消失。
五、总览态为何不应该强行显示编号
ChartCell()的字体随格子尺寸变化:
.fontSize(size>=40?22:(size>=10?5:4))70 列总览格子只有 4vp,即使字体取 4fp,三位色号也无法在单格中辨认。当前调用把显示条件与图纸宽度绑定:
this.ChartCell(cell,this.overviewCellSize(pattern),pattern.width<=48)这条规则体现了信息分层:总览负责整体轮廓,点击后展开态负责逐格编号。与其在 4vp 格子里堆不可读字符,不如保留色块和粗网格,并用“点击图纸放大查看”建立下一步入口。
如果产品要求总览也读编号,应改变交互方式,例如长按弹出单格详情,而不是继续缩字体。
六、视口高度不能只看图纸宽度
现有候选函数按高度设置 380 或 390vp:
privatechartViewportHeight(pattern:Pattern):number{if(pattern.height>=64){return390;}return380;}它表达的是“页面给图纸区域多少高度”,不是纸张真实高度。真实纸高至少还要包含:
functionpaperHeight(height:number,cell:number):number{constheaders=16*2;constbottomPadding=14;returnheaders+height*cell+bottomPadding;}视口高小于纸高时开启纵向滚动;视口高大于纸高时可以按内容高度收缩。把两者混为一个height()值,会出现小图下面大块空白,或大图被裁切却没有滚动距离。
七、统一策略要保留场景名,而不是只返回数字
可以用场景枚举消除三个相似函数:
enumChartMode{Overview,Expanded,Embedded}functioncellSize(width:number,mode:ChartMode):number{if(mode===ChartMode.Overview){returnwidth>=64?4:width>=48?5:8;}if(mode===ChartMode.Expanded){returnwidth>=64?11:width>=48?12:14;}returnwidth>=64?10:width>=48?11:10;}保留ChartMode很重要。若只抽成一张数字表,调用处会出现cellSize(width, 1)之类无法审阅的代码。场景名把“为什么是这个尺寸”留在类型层。
进一步还可以让策略返回showCode、majorGridEvery和fontSize,但不要一次塞入主题颜色、数据筛选等无关职责。
八、未使用函数要纳入静态审计
三组chart*方法当前没有引用。如果准备保留,应给出明确接入点,例如编号页新增一个固定高度的滚动卡片:
Scroll(){this.ChartPaper(pattern,ChartMode.Embedded);}.height(this.chartViewportHeight(pattern)).scrollable(ScrollDirection.Horizontal)若产品已经选择“总览卡片 + 全屏展开”,则这三组方法应删除,避免后来维护者误以为页面存在第三种渲染模式。
审计时可以用文本引用数量作为第一道筛查,但最终要读调用树。函数名出现在注释或同名文档里并不代表已运行,只有从build()或 Builder 路径可达,才算真正接入。
九、用表驱动样本验证几何不变量
几何测试不需要启动页面,纯函数即可覆盖:
constsamples=[{width:47,overview:8,expanded:14},{width:48,overview:5,expanded:12},{width:63,overview:5,expanded:12},{width:64,overview:4,expanded:11},{width:70,overview:4,expanded:11}];除了尺寸相等,还应验证三条不变量:
- 同一宽度下
expanded >= embedded >= overview,除非明确记录例外。 paperWidth = leading + width × cell,最后一列不会超出纸面。- 宽度跨过断点后,纸张总宽不应发生难以解释的巨幅跳变。
例如 63 列总览为24+63×5=339vp,64 列变为24+64×4=280vp,会突然缩小 59vp。这是当前规则的真实结果。它可能符合“64 列进入大图模式”的设计,也可能造成列表卡片视觉跳变,必须由产品和视觉共同确认。
十、真机验收关注三件事
建议准备 47、48、63、64、70 列五张固定样本,在手机、平板和 2in1 上观察:
- 总览纸面是否保持居中,最后一列是否完整。
- 48 与 64 临界点前后,格子和纸面是否出现突兀跳变。
- 展开态三位色号是否可读,粗网格是否仍然清楚。
- 横向滚动范围是否恰好到纸面右边界,没有多余大块空白。
- 字体缩放开启后,编号是否因系统字体倍率溢出。
若最后一列缺失,先复算 leading、padding 和width × cell;若纸面能显示但点击区域偏移,检查交互层是否使用另一套尺寸;若 64 列突然比 63 列小很多,则不是设备偶发问题,而是分段函数的确定行为。
十一、结语
响应式编号图不是“屏幕小就缩一点”,而是先按场景定义信息密度,再让每个场景拥有一致的格子、纸宽、表头和视口几何。拼豆制图现有三套函数提供了清晰起点,也暴露出两个工程问题:断点会造成纸宽跳变,第三套尺寸尚未接入。
把几何收敛为带场景名的纯函数、用 47/48/63/64 边界样本锁住规则,并删除或接入未使用方法,才能让后续增加尺寸、设备形态或缩放手势时,页面仍然只有一份可信的坐标系统。