Swift实现Nested Scroll

概述

2016年终于把学习swift的计划付诸行动,在班车上把v3.0.1版本的Programming Language看完了。但是,“纸上得来终觉浅,绝知此事要躬行”,于是打算用swift把经典的nested scroll实现一遍。 WWDC2013-217的主题是探索(explore) scroll,包含实现imessage中消息滚动时的动画和nested scroll,个中的原理不多说,只简单罗列实现步骤,侧重的还是swift在项目中的应用。

imessage式消息滚动弹性动画

UICollectionView的实现是layoutUICollectionReusableView的结合,因此该动画的实现主要是基于layout的操作。基本步骤如下:

  1. 实现layout子类
  2. 给cell添加动画:UIAttachmentBehavior
  3. 滚动的时候,更改动画的锚点并更新动画:锚点的变化取决于锚点先前位置和手指滑动位置

nested scroll

nested scroll,顾名思义,即几个scroll叠加。滑动的时候,View Tree上处于叶节点位置的view先滑动,滑动到一定程度后,该view的父view继续滚动。基本思路:

  1. 检测滑动的边际,是否超出阈值;未超出阈值的情况下,要让父view禁止滑动
  2. 超出阈值,根据滚动速度计算父view的偏移量,并更新
  3. 滑动停止后,让父view再次响应滑动

在第二步中,设置父view偏移的时候如果使用setContentOffset(_ contentOffset: CGPoint, animated: Bool), animated需为false。

swift相关内容

type casting

swift中数值类型如Float,Double等都是struct;CG中的类型也进行了struct重写。因此,数值之间的转换需要显式转换,否则编译器会报错。
类型检查的时候,直接使用:

if instance is ClassA {
}

需要downcast(从父类转成某一子类),通过as:

for item in itemArray {
            if let attri = item as? UICollectionViewLayoutAttributes {
            }
}

如果确定是某一类型,也可以直接使用 as!

常量定义

需要多个文件共享的常量,可以定义一个文件,然后定义struct,把常量作为变量。为某一类定义的常量,可以通过extension。

示例工程:MessageScrollDynamicNestedScrollView