最近做阅读页的翻页效果的时候,大量的使用了UIPageViewController
,这里记录一下,方便以后使用备忘。
打开这个类的api,发现这个类还是比较简单的,主要是一个初始化方法,一个设置当前页面的方法,还有两个代理,其他的属性大部分都是只读属性,这些属性一般只能在初始化方法中设置。
一. 初始化
- (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(nullable NSDictionary<UIPageViewControllerOptionsKey, id> *)options
主要有三个初始化参数,这里介绍一下:
style
,枚举类型,控制翻页效果
typedef NS_ENUM(NSInteger, UIPageViewControllerTransitionStyle) {
// 仿真翻页,卷曲样式类似翻书效果
UIPageViewControllerTransitionStylePageCurl = 0, // Navigate between views via a page curl transition.
// 滑动翻页,UIScrollView滚动效果
UIPageViewControllerTransitionStyleScroll = 1 // Navigate between views by scrolling.
};
navigationOrientation
,导航方向,枚举类型,水平方向或者垂直方向options
,配置,是一个字典,只有两个Key
-
UIPageViewControllerOptionSpineLocationKey
,定义的是仿真翻页的时候模拟书脊的位置,只有在style为UIPageViewControllerTransitionStylePageCurl
是生效
typedef NS_ENUM(NSInteger, UIPageViewControllerSpineLocation) {
// 非UIPageViewControllerTransitionStylePageCurl时默认值
UIPageViewControllerSpineLocationNone = 0, // Returned if 'spineLocation' is queried when 'transitionStyle' is not 'UIPageViewControllerTransitionStylePageCurl'.
// 书脊位置在最左边,UIPageViewControllerTransitionStylePageCurl仿真翻页时的默认值
UIPageViewControllerSpineLocationMin = 1, // Requires one view controller.
// 书脊位置在中间,设置当前页面的时候需要两个控制器
UIPageViewControllerSpineLocationMid = 2, // Requires two view controllers.
// 书脊位置在最右边
UIPageViewControllerSpineLocationMax = 3 // Requires one view controller.
}; // Only pertains to 'UIPageViewControllerTransitionStylePageCurl'.
2.UIPageViewControllerOptionInterPageSpacingKey
,定义的事滚动翻页的时候两个页面的间距,只有style为UIPageViewControllerTransitionStyleScroll
时才生效,默认值为0
二. 设置当前页面
在创建pageViewController
之后,还需要设置其当前页面,这就需要用到下面这个方法
// Set visible view controllers, optionally with animation. Array should only include view controllers that will be visible after the animation has completed.
// For transition style 'UIPageViewControllerTransitionStylePageCurl', if 'doubleSided' is 'YES' and the spine location is not 'UIPageViewControllerSpineLocationMid', two view controllers must be included, as the latter view controller is used as the back.
- (void)setViewControllers:(nullable NSArray<UIViewController *> *)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion;
这个方法用于设置当前可见的控制器,可以选择时候有动画,
-
viewControllers
, 将要显示的控制器数组,只能是包含controllers
的数组。 -
direction
切换动画的方向 -
animated
bool值,是否显示动画 -
completion
切换完成后的回调
当style为UIPageViewControllerTransitionStylePageCurl
仿真翻页,UIPageViewControllerOptionSpineLocationKey
值为UIPageViewControllerSpineLocationMid
书脊在中间位置,并且属性doubleSided
为YES
时,数组里面必须包含两个控制器,否则会崩溃。
doubleSided
属性
// Whether client content appears on both sides of each page. If 'NO', content on page front will partially show through back.
// If 'UIPageViewControllerSpineLocationMid' is set, 'doubleSided' is set to 'YES'. Setting 'NO' when spine location is mid results in an exception.
@property (nonatomic, getter=isDoubleSided) BOOL doubleSided; // Default is 'NO'.
这个属性定义的事书页的两面是否都显示内容,默认值为NO
。
如果为NO
,则书页内容类似半透明的投射到背面。
当style为UIPageViewControllerTransitionStylePageCurl
仿真翻页,并且UIPageViewControllerOptionSpineLocationKey
值为UIPageViewControllerSpineLocationMid
书脊在中间位置时,属性doubleSided
会被自动设置为YES
,如果为NO
,会崩溃。
三. 数据源与代理方法
pageViewController提供了类似UITableViewController的数据源与代理机制
1.
UIPageViewControllerDataSource
数据源
iOS SDK提供了四个数据源方法,其中两个为@required,另外两个是@optional.
@required
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
这个方法是返回前一个页面的控制器,如果返回nil,则认为当前页面为第一个页面,不可以向前滚动或者翻页
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;
个方法是返回后一个页面的控制器,如果返回nil,则认为当前页面为最后一个页面,不可以向后滚动或者翻页
@optional
这两个方法定义了在水平滚动模式下的一个pageControl,只有在滚动翻页UIPageViewControllerTransitionStyleScroll
并且水平滚动 UIPageViewControllerNavigationOrientationHorizontal
时有效,会显示一个白色圆点的pageControl,在设置方法setViewControllers:...
中后调用,会自动随着滚动更新指示器index
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController API_AVAILABLE(ios(6.0)); // The number of items reflected in the page indicator.
定义指示器的数量
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController API_AVAILABLE(ios(6.0)); // The selected item reflected in the page indicator.
定义指示器的当前index
2.
UIPageViewControllerDelegate
代理
总共有5个可选代理
@optional
// Sent when a gesture-initiated transition begins.
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers API_AVAILABLE(ios(6.0));
这个方法是UIPageViewController开始滚动或翻页的时候触发
// Sent when a gesture-initiated transition ends. The 'finished' parameter indicates whether the animation finished, while the 'completed' parameter indicates whether the transition completed or bailed out (if the user let go early).
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed;
这个方法是在UIPageViewController结束滚动或翻页的时候触发
// Delegate may specify a different spine location for after the interface orientation change. Only sent for transition style 'UIPageViewControllerTransitionStylePageCurl'.
// Delegate may set new view controllers or update double-sided state within this method's implementation as well.
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation API_UNAVAILABLE(tvos);
这个方法是在style是 UIPageViewControllerTransitionStylePageCurl
并且横竖屏状态变化的时候触发,我们可以重新设置书脊的位置,比如如果屏幕是竖屏状态的时候我们就设置书脊位置是UIPageViewControllerSpineLocationMin或UIPageViewControllerSpineLocationMax, 如果屏幕是横屏状态的时候我们可以设置书脊位置是UIPageViewControllerSpineLocationMid
- (UIInterfaceOrientationMask)pageViewControllerSupportedInterfaceOrientations:(UIPageViewController *)pageViewController API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(tvos);
- (UIInterfaceOrientation)pageViewControllerPreferredInterfaceOrientationForPresentation:(UIPageViewController *)pageViewController API_AVAILABLE(ios(7.0)) API_UNAVAILABLE(tvos);
这两个方法设置了UIPageViewController支持的屏幕类型