列表中的某行高度改变,后面的内容位置都会移动。如果只保留原滚动数字,用户看到的行可能突然换掉。可以用行的身份和行内偏移保存阅读位置。
初始取顶部第一个可见行作为锚点,同时记住已经滚过这行的像素数。后续只在锚点上方修改、插入或删除行;新滚动量等于锚点之前所有行的高度之和加原来的行内偏移,再限制到可滚动范围。
这一例的完整输入
初始行的编号和高度为[[0, 16], [1, 10], [2, 11], [3, 17], [4, 11], [5, 12], [6, 14], [7, 15], [8, 18], [9, 8], [10, 10], [11, 11]],锚点编号5,行内偏移6,窗口高27。插入操作格式为目标行、新编号、新高度。
逐项计算记录
操作 | 滚动量 | 未限幅目标 | 可见行及露出像素 ['initial'] | 71 | 71 | [[5, 6], [6, 14], [7, 7]] ['height', 1, 20] | 81 | 81 | [[5, 6], [6, 14], [7, 7]] ['insert', 2, 20, 15] | 96 | 96 | [[5, 6], [6, 14], [7, 7]] ['delete', 0] | 80 | 80 | [[5, 6], [6, 14], [7, 7]] ['height', 3, 7] | 70 | 70 | [[5, 6], [6, 14], [7, 7]] ['insert', 4, 21, 20] | 90 | 90 | [[5, 6], [6, 14], [7, 7]]
读表时先把输入与计算后的结果分开。空值表示这一步没有适用对象或没有可用结果,不应自动换成零。编号只负责识别本例中的元素,同一个数字出现在不同字段时,要先确认它代表位置、对象还是数值。
怎样复核和使用
每次操作后重算可见行和各行实际露出的像素。锚点身份不依赖它现在排第几;没有触碰滚动上下边界时,锚点顶部相对窗口的位置应保持为原偏移的相反数。
本例的行高固定为正整数,没有异步图片加载、折叠动画或锚点本身被删除的情况。若锚点被删除,需要事先约定换成邻近哪一行,不能直接沿用失效的编号。
可以先遮住记录表,只按上述规则重算前两步,再选择一个边界条件重新试算。若结果不一致,应逐项检查输入顺序、端点是否包含以及状态在哪一步更新;不要只看最终合计相同就认为中间处理也完全正确。
