在我的设置中,我有一个带有芯片样式的水平集合视图,在初始加载时,默认情况下选择第一个芯片,并对芯片进行API调用,并将其数据加载到下面的垂直UICollectionView中。
在点击UICollectionView中的任何芯片时,将启动一个API调用,并使用scrollToItem(at: selectedChipIndexPath, at: .centerHorizontally , animated: true)
将所选单元格滚动到collectionview的中心。另外,我必须重新加载上次选择的和当前选择的indexPath,以表明新单元格被选中。
如果用户点击芯片,查看下面加载的数据,然后点击下一个芯片,一切正常。
但是,如果用户快速点击连续的芯片,那么scrollToItem(at: selectedChipIndexPath, at: .centerHorizontally , animated: true)
有时会出现滚动动画故障,导致不愉快的UX体验。
下面是我的代码:
horizontalCollectionView.reloadItems(at: [lastSelectedIndexPath, selectedChipIndexPath])
// API Call
/*
This is an async call, which ones finishes informs the ViewController to the update it's vertical collection view with new data
*/
viewModel.fetchProductData(forPositon: selectedChipIndexPath)
DispatchQueue.main. asyncAfter ( .now() + .seconds(0.4)) {
horizontalCollectionView.scrollToItem(at: selectedChipIndexPath, at: .centerHorizontally , animated: true)
}
如果我不延迟几毫秒的滚动,那么集合视图的滚动动画开始出现非常严重的故障。
因此,任何人都可以指出我在正确的方向,我如何处理或排队多个scrollToItem(at:at:animated:)
调用,使我的收藏查看滚动动画不出故障。
我确实尝试在批量更新中 Package scrollToItem(at:at:animated:)
,但它不起作用。
更新1:
以下是我的UI的主要外观
水平集合视图:产品类别的
垂直集合视图:产品本身
更新二:
DonMag提供的解决方案可以工作,但它引入了另一个问题,根据我的设计,当选择时,我必须将芯片内的UILabel的字体类型从常规更改为粗体,这样做会导致标签框架大小增加,并且对于大多数文本,标签会被剪切,因为我只是操纵视图而不是重新加载单元格本身。
我试图使CollectionView流布局无效。但它再次给我带来了同样的问题滚动故障。
1条答案
按热度按时间e0bqpujr1#
如果没有看到完整的代码,问题可能是由于您重复调用
.reloadItems(...)
而导致的。如果您这样做只是为了更改所选单元格的外观,则没有必要。
相反,让集合视图跟踪选定的单元格(默认情况下),并让单元格根据其选定状态修改自己的外观。
例如-如果我们以这样的典型方式创建一个具有单个标签的单元格:
我们已经覆盖了
var isSelected: Bool
...集合视图将在需要时设置该属性,现在我们的单元格自动更新其“selected / un-selected”外观。无需调用
.reloadItems
使用上面单元格的水平集合视图的视图控制器示例-注意,我创建了4个样本标签的“重复集”(前缀为1-4),所以我们有足够的单元格可以滚动:
编辑- * 附加要求:选定时,单元格字体更改为粗体,而不会导致单元格大小更改... *
最简单的方法是在单元格中添加两个标签-一个是粗体,另一个是普通字体。
设置约束,以便粗体标签将控制宽度,而常规标签将比必要的略宽。
选择时显示粗体标签,不选择时显示常规标签。
所以,稍微修改了上面的细胞类:
然后在控制器的
cellForItemAt
中,我们将设置单元格的title
属性,而不是设置“single”标签的文本,这将在两个标签中设置相同的文本:编辑2- * 响应有关以编程方式选择的评论. *
第一,不要打电话:
它不会告诉集合视图该单元格已被选中。
这是以编程方式选择单元格的正确方法(在本例中,我们希望选择单元格/项目
5
并将其滚动到中心):请注意,* 以编程方式 * 选择单元格将 * 不 * 调用
didSelectItemAt
委托函数。调用它是为了让您知道 user 选择了一个单元格。所以,如果你想以编程方式选择一个单元格,并且你想发生一些事情,那么就用那个“做一些事情”代码来跟踪它。
举例来说: