带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画
Posted
技术标签:
【中文标题】带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画【英文标题】:Incomplete delete animation for a single row horizontal UICollectionView with UICollectionViewCompositionalLayout 【发布时间】:2020-09-08 16:39:14 【问题描述】:目前,我有一个水平单行 UICollectionView
和 UICollectionViewCompositionalLayout
[All] [Calendar] [Home2] [Work3] [Work4] ... [Work8] [⚙]
UICollectionView
,充当可滚动的 Tab 布局导航栏。
当用户切换到[⚙]
页面时,他可以删除自己之前的标签。在这种情况下,在第一次删除操作期间,标签[Work8]
将被删除。
这是实现此目的的简单代码。
https://github.com/yccheok/ios-tutorial/blob/debug/TabDemo/TabDemo/ViewController.swift#L144
func debug()
if tabInfos.count < 2
return
let index = tabInfos.count-2
tabInfos.remove(at: index)
let indexPath = getIndexPath(index)
self.tabCollectionView.deleteItems(at: [indexPath])
// TODO: Possible solution.
/*
self.tabCollectionView.reloadData()
DispatchQueue.main.async()
let indexPath = self.getIndexPath(self.tabInfos.count-1)
self.tabCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
self.tabCollectionView.scrollToItem(at: indexPath, at: .right, animated: true)
*/
// Clear left/ right cached view controllers - https://***.com/a/21624169/72437
pageViewController.dataSource = nil
pageViewController.dataSource = self
// Don't forget to adjust the selection index.
if index < self.selectedTabInfoIndex
selectedTabInfoIndex -= 1
奇怪的结果
https://www.youtube.com/watch?v=Wzgb4QErUes(完整删除动画请参考此视频)
这是删除前的样子
如视频中所见,删除[Work8]
后,左侧标签([Work3]
)不可见
我的预期结果是,[Work3]
应该立即可见,无需用户进行任何额外操作。我需要点击UICollectionView
,移动一下,只会出现所有的标签
我不喜欢使用reloadData
,因为
-
不会保留
UICollectionView
的滚动位置。
它没有动画。
你知道这个奇怪的动画结果的根本原因是什么吗?
这是试用的完整源代码 - https://github.com/yccheok/ios-tutorial/tree/debug(文件夹 TabDemo)
【问题讨论】:
如果你在 git 上上传一个简单的可重现项目并将其链接到这里会很好 我已经发布了github.com/yccheok/ios-tutorial/releases/tag/debug(在文件夹github.com/yccheok/ios-tutorial/tree/debug(文件夹TabDemo)下) 我下载了你的演示项目,用 Xcode 12.0 beta 5 (12A8189h) 编译它,然后在 iPhone 11 Pro 模拟器上运行它。当我在“设置”选项卡中点击“删除”时,“工作 3”选项卡会正确显示。 【参考方案1】:您需要稍微不同地配置布局 - 使用显式配置而不是正交行为。
这里是固定部分。使用 Xcode 11.7 / iOS 13.7 测试
private func layoutConfig() -> UICollectionViewCompositionalLayout
let configuration = UICollectionViewCompositionalLayoutConfiguration()
configuration.scrollDirection = .horizontal
return UICollectionViewCompositionalLayout(sectionProvider: (sectionNumber, env) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .absolute(44))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 1
return section
, configuration: configuration)
【讨论】:
我想我需要使用section.orthogonalScrollingBehavior = .continuous
来实现水平滚动。我没有注意到这种configuration.scrollDirection = .horizontal
技术。谢谢你告诉我。【参考方案2】:
尚未绘制,因为当您单击 Work8 的删除时,它已超出视口。这对于 iOS 来说很典型。
你可以强制重绘而不是reloadData
:
myViewOrComponent.setNeedsDisplay();
【讨论】:
我尝试在UICollectionView
中调用setNeedsDisplay
,在deleteItems
之后,这没有帮助。【参考方案3】:
你能试试这个吗,这里你可能需要处理可滚动的 contentSize 和 scrollPosition。
func debug()
if tabInfos.count < 2
return
let index = tabInfos.count-2
tabInfos.remove(at: index)
var indexPath = getIndexPath(index)
self.tabCollectionView.deleteItems(at: [indexPath])
tabCollectionView.collectionViewLayout = layoutConfig()
print(selectedTabInfoIndex)
// Don't forget to adjust the selection index.
if index < self.selectedTabInfoIndex
selectedTabInfoIndex -= 1
indexPath = getIndexPath(selectedTabInfoIndex)
self.selectTab(selectedTabInfoIndex)
【讨论】:
以上是关于带有 UICollectionViewCompositionalLayout 的单行水平 UICollectionView 的不完整删除动画的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 uuencode 的“sendmail”发送邮件,并带有主题
如何翻转正面带有标签而背面带有另一个标签的视图 - 参见图片
CakePHP 如何处理带有/不带有 'id' 字段的 HABTM 表?
带有 RecyclerView 的 DialogFragment 比带有 Recyclerview 的 Fragment 慢