滚动 UITableView 时 iOS Expanded/Selected Custom UITableViewCells 状态变化
Posted
技术标签:
【中文标题】滚动 UITableView 时 iOS Expanded/Selected Custom UITableViewCells 状态变化【英文标题】:iOS Expanded/Selected Custom UITableViewCells state changes when scrolling UITableView 【发布时间】:2016-02-06 06:25:31 【问题描述】:我的表格视图中有一个自定义单元格列表,当我滚动时,一切似乎都很好,并且单元格的顺序似乎相同。我的单元格有一些功能 - 当我选择一个单元格(并且它动态扩展)时,背景颜色会发生变化和一些其他自定义单元格属性。一旦我这样做,然后我开始滚动,我什至没有触摸过的不同单元格显示出来,被选中(扩展)并且单元格只有在我手动选择正确数据时才会更新。我似乎看到了重复和各种疯狂。
我知道到目前为止这里有很多关于此的帖子,但对我来说,到目前为止没有任何效果。想知道我能做些什么来阻止这种荒谬的行为。
我发布了一些代码,让您更好地了解我在做什么。我知道“dequeueReusableCellWithIdentifier”是罪魁祸首,但不知道有什么替代方法。
作为旁注,这是一个 tableview(它自己的 xib),它是一个大视图(也是 xib)的子视图。我也已经为 tableview 注册了笔尖。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:myIndentifier forIndexPath:indexPath];
if(self.currentSelectedIndex)
if(self.previousSelectedIndex)
//collapse cell
//configure cell in method(change background color etc)
else
//expand cell
//configure cell in method(change background color etc)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
self.currentSelectedIndex = indexPath;
[tableView beginUpdates];
if(self.currentSelectedIndex)
if(self.previousSelectedIndex && (self.previousSelectedIndex != self.currentSelectedIndex))
[tableView reloadRowsAtIndexPaths:@[self.currentSelectedIndex, self.previousSelectedIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[tableView reloadRowsAtIndexPaths:@[self.currentSelectedIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
if(self.previousSelectedIndex == self.currentSelectedIndex)
self.previousSelectedIndex = nil;
else
self.previousSelectedIndex = self.currentSelectedIndex;
我能做什么或如何确保列表中的其他内容“似乎”没有被选中(扩展)或防止在我滚动时出现重复项?我已经跟踪了我当前和最后选择的索引(如代码所示),所以我想我可以以某种方式使用它吗?
【问题讨论】:
我也会在这里添加这个 - 只是作为一个花絮。在表格视图中使用 1 个单元格进行了尝试。它崩溃了。当我快速向上滑动时,它又回到了视野中,它神奇地展开了。只有当我与它互动时,它才会恢复到原来的状态。 更新:我想我找到了我的问题。 I was playing around with that one cell - and it turns out that when selecting a cell and the previousIndexPath was equal to the new currentIndexPath i wasn't setting the currentIndexPath back to nil (no selections - everything back at default state).因此,当以任何方式(滚动、上拉或下拉等)重新加载 tableview 时,它仍然认为有一个 selectedIndex - 我当时的逻辑失败了。但很高兴知道你能做到,只是要小心:) 谢谢你的帮助,我把你原来的链接帖子放在手边。 【参考方案1】:重复使用出队的单元格
知道单元格被重复使用,因此UITableViewCell
的外观在该单元格的整个生命周期内都保持不变。
这意味着,如果您没有显式地 reset
显示单元格的所有表示视图,而只是在 cellForRowAtIndexPath
中原封不动地返回它,那么您返回的可能是当前选择(或取消选择)的缓存单元格。
重置表格单元格的可能位置是prepareForReuse
。
设计说明:
您如何维护self.currentSelectedIndex
和self.previousSelectedIndex
?这通常非常危险,因为您正试图复制 UITableView
行为。例如,它不太可能与多项选择一起使用。当操作系统didDeselectRowAtIndexPath
时,设置活动 选择不太可能处理情况,例如键盘关闭。
【讨论】:
在 didSelectRowAtIndexPath 中 - 我添加了该代码供您查看。基本上,每次我选择一个索引时,我都会将其设置为当前索引。这应该考虑到每种情况 - 第一次选择索引,连续两次选择相同的单元格(以前和当前相同)并选择当前索引,然后选择不同的索引。如果您有任何问题或有任何想法,请告诉我。 是的,就我而言,要回答您更新的回复,一次只能有一个“选择/扩展”单元格。如果您有一个已展开的单元格,而您选择了另一个单元格,则前一个单元格将被折叠,而新的单元格将被展开。所以一次没有多项选择。 是否使用 didSelect/didDeselect 作为重新加载这些行的方法,足以解决问题?该链接似乎暗示了这一点。例如,在我的情况下,如果在进行选择后,previousIndex 不等于当前索引,那么我们知道它们是不同的索引。应该取消选择前一行,选择新选择的行。 您在上面说过“重置返回给您的单元格的颜色/字体/外观..”我不确定您的意思是什么...? 我还使用 heightForRowAtIndexPath 来跟踪我当前和以前选择的索引,以便展开/折叠。这可能不需要碰我不确定..如果你愿意,我也可以给你那个代码。从检查所有情况的意义上讲,它确实模仿了 cellForRowAtIndexPath - i,,e (如果它是迄今为止第一个选择的索引,则展开单元格,如果没有,您是否连续两次触摸相同的索引(previous = current)? -然后折叠单元格,如果您选择一个单元格和上一个!= 当前然后展开新索引,折叠上一个..以上是关于滚动 UITableView 时 iOS Expanded/Selected Custom UITableViewCells 状态变化的主要内容,如果未能解决你的问题,请参考以下文章
IOS - 滚动时将 UIView 保持在 UITableView 之上