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