iOS上的Messenger Messenger头像动画
介绍
当您的消息收件人看到您的消息时,Facebook Messenger具有特殊的可见状态动画。 它旨在向发件人提供信息通知,告知您的受众群体正在积极在线并实时查看您的消息。 此功能的商业价值不仅是鼓励人们发送更多实时消息,还使经常发送消息的人们感到高兴。 1:1聊天以及群聊中都可以使用此功能。 我创建了一个简短的gif,以说明所看到的头部移动动画:
那么我们从哪里开始呢?
#1 Vanilla UICollectionView
首先,我确定的一件事是,我们应该使用UICollectionView 。
UICollectionView不仅支持自定义布局,而且还具有用于插入/更新/删除/移动操作的本机动画。 因此,最重要的一点是移动动画。 从Apple文档获取UICollectionView:
func moveItem(at indexPath: IndexPath,
to newIndexPath: IndexPath)
我们可以使用它来实现看到的脑袋之间的移动动画。 UICollectionView在内部管理所有动画详细信息,并通过配置正确的动画属性来处理所有繁重的工作,并将其发送给Core Animation以获得实际效果。
所以现在的问题是,我们如何为这个UICollectionView构造数据模型? 这很容易,我们只需要创建一个一维对象数组,其中包含一个Message或一个User (对于可见头)。
现在,我们有了三个节控制器,并且HScrollSeenHeadSectionController包含另一个H滚动UICollectionView用于显示的头部。 这次我不打算使用自定义UICollectionViewLayout,因为我认为嵌套的SectionController可以自动处理。 但是,这就是我得到的:
事实证明,使用嵌套部分控制器作为所有可见头部的容器存在一些问题:
- 没有移动动画。 数据模型现在变为二维数组,我们必须模拟更新的数据结构。 IGListKit不会将其视为移动动画,因为从技术上讲,我们不能在两个不同的 UICollectionView之间移动单元格。
- H滚动UICollectionView的布局不正确。 为了布局从右边缘开始对齐的可见头,我们必须为此H滚动组件专门实现一个新的自定义UICollectionViewLayout。
我放弃了这种方法,我认为需要在库级别解决此问题,以支持不同UICollectionView之间的单元格移动动画,这似乎并不简单。
#3 IGListKit +自定义UICollectionViewLayout
最后,我决定使用#1中的Custom UICollectionViewLayout并将其与IGListKit结合使用。 基本上,相同的想法是使用一维数组并使用单个UICollectionView为屏幕上的所有UI元素提供动力。
使用IGListKit的好处是,它全部是数据驱动的,无需了解有关何时移动或何时删除的UICollectionView详细信息。 图书馆会自动为我们计算它,我们可以这样做:
如果我们在第3行点击最右边的seeedHead,则需要对两个seehead进行动画处理,因此我们的插入和删除更新集为:
- 插入到[第3节,项目0]上 ,元素类型: seenhead1
- 在[第2节,项目0]上删除,元素类型: seenhead0 ,
- 并且由于我们要移动的位置会影响到seehead0之后的所有seehead ,因此我们将需要为[section 2,item 0] (元素类型: seehead1)添加插入。
- 最后,对于initialLayoutAttributesForAppearingSupplementaryElement和finalLayoutAttributesForDisappearingSupplementaryElement ,我们可以将userId与具有当前布局属性的先前布局属性相关联,这样我们可以进行快速查找并轻松实现这两个API。
使用补充视图方法的要点是正确计算需要删除并插入哪个补充视图,否则将不会调用数据源API“ viewForSupplementaryElementOfKind”,这将使seeedHead保持不变。
随意查看补充视图方法的简单实施的源代码:链接
学习
当然,通过构建自己的自定义UIScrollView(可以控制动画或布局的所有粒度)来实现此动画的方法有很多。 但是我发现将UICollectionView与自定义布局一起使用是最简单的方法。
这个周末小项目还有许多其他有趣的技术细节:
- 我们如何为看到的标题和消息生成生产质量代码的自定义UICollectionViewLayout的实现细节,因为挑战在于如何构建具有60fps滚动性能的有效布局。
- 客户/服务器通信对于可见状态的挑战,尤其是在发生许多异步可见头部突变的群聊环境中。 大规模处理绝对是一个有趣的工程问题。
谢谢阅读! 让我知道您是否有任何问题,欢迎反馈!
lorixx / TestSeenheadWithIGListKit
TestSeenheadWithIGListKit – Messenger通过IGListKit看到头部移动
github.com
参考文献
- https://github.com/Instagram/IGListKit/
- https://www.objc.io/issues/1-view-controllers/lighter-view-controllers/
- https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52
- https://developer.apple.com/documentation/uikit/uicollectionview