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