结束显示时如何重新加载 collectionView 单元格?
How to reload collectionView cell when it did end displaying?
我创建了一个用户入职培训作为 Collection View
,有 5 个单元格(页面)。
我有 2 种类型的集合视图 Items
:welcomeCell
它始终是入职培训中的第一个单元格(indexPath.item == 0
)和 tutorialCell
(所有其他单元格) ) 具有 tableView
并且可以垂直滚动其内容。
我想添加下一个行为:
- 用户滚动
tableView
内容并滑动到下一页
- 如果用户滑动回到他滚动的页面,我希望页面布局像最初设置的那样重新加载。
现在,如果用户滑动到他滚动的页面,他将看到他结束滚动的页面位置。
我建议 collectionView
内容可以在 didEndDisplaying
方法中重新加载:
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if indexPath.item != 0 {
self.collectionView.reloadItems(at: [indexPath])
}
}
但是使用这段代码我收到了一个奇怪的单元格行为:我可以在一个页面上向上滑动 tableView
并且出现的内容位置将在另一个页面上,但是一些页面可以加载正常的内容位置。这是一个 GIF:GIF
我也在 scrollViewDidScroll
和 scrollViewDidEndDecelerating
中尝试了 collectionView.reloadData()
,但收到了类似的行为。
您能否分享一些经验并帮助了解什么是适合我的案例的最佳做法?也许我应该找到一种根本不重新加载页面内容的方法,而是在约束中重新加载 imageView
高度锚?
尝试使用 DispatchQueue 方法:
if indexPath.item != 0 {
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
经过一些实验和信息研究,我得到了以下结果:
我稍微修改了我的初始目标:使用下面的代码,如果用户在滑动时将决定停留在当前页面,则不会重新加载数据。在其他情况下 - 重新加载。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OnboardingCell", for: indexPath) as! OnboardingCollectionViewCell
// reset the current tableView position to initial one
if cell.tableView.window != nil {
cell.tableView.contentOffset = CGPoint.zero
cell.tableView.layoutIfNeeded()
cell.tableView.reloadData()
}
return cell
}
private var activePage = 0 {
didSet {
if activePage != oldValue {
// the method will fire cellForItemAt code
collectionView.reloadData()
}
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
for cell in collectionView.visibleCells {
activePage = collectionView.indexPath(for: cell)?.row ?? 0
}
}
此外,如果您有导航控件,如上一个和下一个按钮,请不要忘记像这样重新加载数据:
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
collectionView.reloadData()
}
我创建了一个用户入职培训作为 Collection View
,有 5 个单元格(页面)。
我有 2 种类型的集合视图 Items
:welcomeCell
它始终是入职培训中的第一个单元格(indexPath.item == 0
)和 tutorialCell
(所有其他单元格) ) 具有 tableView
并且可以垂直滚动其内容。
我想添加下一个行为:
- 用户滚动
tableView
内容并滑动到下一页 - 如果用户滑动回到他滚动的页面,我希望页面布局像最初设置的那样重新加载。
现在,如果用户滑动到他滚动的页面,他将看到他结束滚动的页面位置。
我建议 collectionView
内容可以在 didEndDisplaying
方法中重新加载:
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if indexPath.item != 0 {
self.collectionView.reloadItems(at: [indexPath])
}
}
但是使用这段代码我收到了一个奇怪的单元格行为:我可以在一个页面上向上滑动 tableView
并且出现的内容位置将在另一个页面上,但是一些页面可以加载正常的内容位置。这是一个 GIF:GIF
我也在 scrollViewDidScroll
和 scrollViewDidEndDecelerating
中尝试了 collectionView.reloadData()
,但收到了类似的行为。
您能否分享一些经验并帮助了解什么是适合我的案例的最佳做法?也许我应该找到一种根本不重新加载页面内容的方法,而是在约束中重新加载 imageView
高度锚?
尝试使用 DispatchQueue 方法:
if indexPath.item != 0 {
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
经过一些实验和信息研究,我得到了以下结果:
我稍微修改了我的初始目标:使用下面的代码,如果用户在滑动时将决定停留在当前页面,则不会重新加载数据。在其他情况下 - 重新加载。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OnboardingCell", for: indexPath) as! OnboardingCollectionViewCell
// reset the current tableView position to initial one
if cell.tableView.window != nil {
cell.tableView.contentOffset = CGPoint.zero
cell.tableView.layoutIfNeeded()
cell.tableView.reloadData()
}
return cell
}
private var activePage = 0 {
didSet {
if activePage != oldValue {
// the method will fire cellForItemAt code
collectionView.reloadData()
}
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
for cell in collectionView.visibleCells {
activePage = collectionView.indexPath(for: cell)?.row ?? 0
}
}
此外,如果您有导航控件,如上一个和下一个按钮,请不要忘记像这样重新加载数据:
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
collectionView.reloadData()
}