6.IOS(swift)-scrollView ·分页的几种实现方式

利用 UIScrollView 有多种方法实现分页,但是各自的效果和用途不尽相同,其中方法 2 和方法 3 的区别也正是一些同类 App 在模仿 Glow 的首页 Bubble 翻转效果时跟 Glow 体验上的的差距所在(但愿他们不会看到本文并且调整他们的实现方式)。本例通过三种方法实现相似的一个场景,你可以通过安装到手机上来感受三种实现方式的不同用户体验。

1.pagingEnabled

这是系统提供的分页方式,最简单,但是有一些局限性:

<li>只能以 frame size 为单位翻页,减速动画阻尼大,减速过程不超过一页
<li>需要一些 hacking 实现 bleeding 和 padding(即页与页之间有 padding,在当前页可以看到前后页的部分内容)

有简单实现 bleeding 和 padding 效果的代码,主要的思路是:

<li>让 scroll view 的宽度为 page 宽度 + padding,并且设置 clipsToBounds 为 NO
<li>这样虽然能看到前后页的内容,但是无法响应 touch,所以需要另一个覆盖期望的可触摸区域的 view 来实现类似 touch bridging 的功能
适用场景:上述局限性同时也是这种实现方式的优点,比如一般 App 的引导页(教程),Calendar 里的月视图,都可以用这种方法实现。


Paste_Image.png

2.Snap

这种方法就是在 didEndDragging 且无减速动画,或在减速动画完成时,snap 到一个整数页。核心算法是通过当前 contentOffset 计算最近的整数页及其对应的 contentOffset,通过动画 snap 到该页。这个方法实现的效果都有个通病,就是最后的 snap 会在 decelerate 结束以后才发生,总感觉很突兀。

修改 targetContentOffset

通过修改 scrollViewWillEndDragging: withVelocity: targetContentOffset: 方法中的 targetContentOffset 直接修改目标 offset 为整数页位置。其中核心代码:

func nearestTargetOffsetForOffset(offset:CGPoint)->CGPoint{
        var pageSize:CGFloat = BUBBLE_DIAMETER2+BUBBLE_PADDING2
        var page:Int = Int(roundf(Float(offset.x) / Float(pageSize)))
        var targetX:CGFloat = CGFloat(pageSize) * CGFloat(page)
        return CGPointMake(targetX, offset.y)
}

func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        var targetOffset:CGPoint = self.nearestTargetOffsetForOffset(targetContentOffset.memory)
        targetContentOffset.memory.x = targetOffset.x
        targetContentOffset.memory.y = targetOffset.y
}

适用场景:方法 2 和 方法 3 的原理近似,效果也相近,适用场景也基本相同,但方法 3 的体验会好很多,snap 到整数页的过程很自然,或者说用户完全感知不到 snap 过程的存在。这两种方法的减速过程流畅,适用于一屏有多页,但需要按整数页滑动的场景;也适用于如图表中自动 snap 到整数天的场景;还适用于每页大小不同的情况下 snap 到整数页的场景(不做举例,自行发挥,其实只需要修改计算目标 offset 的方法)。

Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • UIScrollView (包括它的子类 UITableView和UICollectionView)是iOS开发中...
    博BlingBing阅读 2,255评论 0 7
  • UIBezierPath Class Reference 译:UIBezierPath类封装了Core Graph...
    鋼鉄侠阅读 1,823评论 0 3
  • 转载:http://www.cocoachina.com/swift/20161201/18198.html 前言...
    F麦子阅读 4,422评论 2 8
  • 因为一场梦境,那些渐被遗忘又悄悄显露的痴心杂念,继续叨扰着生活。半夜腾起也只为一场记起。人的痛苦或幸福在于,无论怎...
    青春被忘路阅读 187评论 0 0
  • 这两天又带着女儿看病奔波着。昨天到了医院复诊,医生让拍CT看看鼻子的情况。挤电梯,跑来跑去,准备拍片子,人家说孩子...
    念恩2015阅读 201评论 0 0