要实现这种效果:
UIScrollView ( base scroll ) 上面放 UIPageViewController,
UIPageViewController 有很多 Page, 一个 page 是一个 UIViewController,
page 上面可以放 UIScrollView ( child scroll )
需要
base scroll 可以滑, 他的内容高度 = 子滚动视图的内容高度 + 子滚动视图之上内容的高度
base scroll 的 content size’s height = child scroll content size’s height + size’s height of view above child scroll
本文主要参考: bawn/Aquaman
实现的思路
类似的效果,上面的思路挺直观
不方便实现
试考虑下面场景:
上面放的 UIPageViewController,从一个 page 滑到另一个 page,
base scroll 的 content size’s height = 子滚动视图 1 的内容高度 + 固定高度 ( header + menu )
变成
base scroll 的 content size’s height = 子滚动视图 2 的内容高度 + 固定高度 ( header + menu )
可能有抖动
UI 就是障眼法
UIScrollView ( mainScrollView , 竖着滑 ) 上面放 UIScrollView ( contentScrollView 横着滚 ),
contentScrollView 上面放 contentStackView ( UIStackView ),
contentStackView 有很多 Page, 一个 page 就是,上面提到的 UIScrollView ( child scroll )
UIScrollView ( contentScrollView 横着滚 ), 其 isPagingEnabled = true
这样就模拟了,UIPageViewController 的滑动翻页效果
实现细节
lazy public private(set) var mainScrollView: AquaMainScrollView = {
let scrollView = AquaMainScrollView()
scrollView.delegate = self
scrollView.am_isCanScroll = true
return scrollView
}()
手势兼容,滚动区域控制:
-
如果不加这一段,child scroll 滚动无效, 滚的就是 mainScrollView ( 竖着滑 )
-
加了这一段,child scroll 上面,其独立滚动,
child scroll 上面固定高度的共用视图, 滚的是 mainScrollView
public class AquaMainScrollView: UIScrollView, UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// 子视图,不是 UIScrollView, 不用考虑
guard let scrollView = gestureRecognizer.view as? UIScrollView else {
return false