虚拟列表从下往上拖动,列表项按下状态显示异常,严重问题。

从上往下拖动没问题,非虚拟列表没问题
我记录了问题,以及详细的复现步骤,从下往上拖动时触发列表刷新时,将所有正在显示的列表项替换了对象,包括我正在按着的列表项,导致按下状态的列表项被回收到对象池,然后再拖动,被其他列表项使用了。
应该是严重bug。
使用长条型的列表项容易复现
已邀请:

谷主

赞同来自:

用官方demo测试。

AILHC

赞同来自:

官方demo同样有问题,我点的是左下角的列表项,但是你看到,右上角露出的列表项居然显示成按下状态

谷主

赞同来自:

我按你的步骤去测试,没有发现异常。

AILHC

赞同来自:

这个问题,我这边已经解决了。
这个问题别人也有问过https://ask.fairygui.com/?/question/4182,类似,应该是同一个问题。

问题的原因是,在列表向前拖动,也就是forward的情况处理时,判断列表项是否能重用是根据这个列表项是否是当前列表 显示的最后一个,这个时候就会出现,我列表项还在显示,但却被回收到对象池了。
 
//GList.handleScroll1
var oldFirstIndex = this._firstIndex;
this._firstIndex = newFirstIndex;
var curIndex = newFirstIndex;
var forward = oldFirstIndex > newFirstIndex;
var childCount = this.numChildren;
var lastIndex = oldFirstIndex + childCount - 1;
var reuseIndex = forward ? lastIndex : oldFirstIndex;
然后渲染到这个列表项时,通过判断

while (curIndex < this._realNumItems && (end || curY < max))
它还在显示区域,而且ii.obj==null,
于是从对象池中拿另外一个对象出来渲染。
如果渲染逻辑中有赋值loader显示图片的就会发现闪烁了。
因为它被回收又拿出来渲染了。

看谷主是否采纳了。
在GList的handleScroll1函数中
//搜索最适合的重用item,保证每次刷新需要新建或者重新render的item最少
if (forward) {
for (j = reuseIndex; j >= oldFirstIndex; j--) {
ii2 = this._virtualItems[j];
if (ii2.obj && ii2.updateFlag != this.itemInfoVer && ii2.obj.resourceURL == url && ii2.obj._y > max) {
if (ii2.obj instanceof fgui.GButton)
ii2.selected = ii2.obj.selected;
ii.obj = ii2.obj;
ii2.obj = null;
if (j == reuseIndex)
reuseIndex--;
break;
}
}
}
这个函数是处理横向流动类型的列表的,所以在处理列表向前拖动时(fowerd)加了个条件判断:
ii2.obj._y > max
判断这个列表项对象是否超出渲染范围,如果超出再进行重用。
对出处理竖向流动的,可以加 ii2.obj._x > max

谢谢谷主,听我解释那么多。
一直说是我逻辑问题,只能自己翻找源码,解决问题了。
可能是对虚拟列表的重用理解不同,希望能采纳吧。

要回复问题请先登录注册