前言
由于公司要開(kāi)發(fā)一款小說(shuō)類閱讀APP,其中體驗(yàn)上非常重要的一點(diǎn)便是翻頁(yè)效果。為了實(shí)現(xiàn)翻頁(yè)效果,我查詢了很多資料后選擇使用了UIPageViewController。原因很簡(jiǎn)單,使用方便,功能強(qiáng)大,開(kāi)發(fā)速度快。首先,我們先看看翻頁(yè)效果圖:
結(jié)構(gòu)
在使用UIPageViewController前,我們應(yīng)該先搞清楚它的層次結(jié)構(gòu)。(這里是我在使用過(guò)程中的理解,如有不對(duì),歡迎指出)。
UIPageViewController作為子控制器加載在viewController上。作為文本控制器的容器,且提供翻頁(yè)的動(dòng)畫效果。
創(chuàng)建一個(gè)TextViewController,用來(lái)顯示文本,裝入pageViewController中。
所以,pageViewController只是提供一個(gè)翻頁(yè)特效的容器,真正顯示在界面上的是里面的TextViewController。到這里是我對(duì)pageViewController有一個(gè)初步的理解。
使用
1.初始化
- (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(nullable NSDictionary*)options
UIPageViewController 為我們提供了2種翻頁(yè)樣式,一種是擬真一種是滾動(dòng)。只需要使用系統(tǒng)的構(gòu)造方法返回一個(gè)UIPageViewController的對(duì)象。并且設(shè)置它的代理和數(shù)據(jù)源并把它加入到控制器中就可以了
pageViewController.delegate = self;
pageViewController.dataSource = self;
[self addChildViewController:pageViewController];
[self.view addSubview:pageViewController.view];
通過(guò)提供的set方法將textController裝入pageViewController中,這個(gè)set方法提供了一種樣式,決定翻頁(yè)是縱向還是橫向。
typedef NS_ENUM(NSInteger, UIPageViewControllerNavigationDirection) {
UIPageViewControllerNavigationDirectionForward,//橫向,像書一樣
UIPageViewControllerNavigationDirectionReverse//縱向,像日歷一樣
};
BookTextController *readerController = [BookTextController new];//展示文本的控制器
[_pageViewController setViewControllers:@[ readerController ]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
2.delegate和dataSource
//向前翻頁(yè)
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
//向后翻頁(yè)
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;
從聲明中我們不難發(fā)現(xiàn)返回的是一個(gè)UIViewController對(duì)象,這個(gè)對(duì)象將重新裝入pageViewController中,從而顯示在界面上。其中參數(shù)中的viewController為當(dāng)前顯示的控制器(這個(gè)參數(shù)在使用doubleSided屬性時(shí)非常重要,后面會(huì)講到)。知道這2個(gè)方法的作用后,pageViewController使用起來(lái)就非常簡(jiǎn)單了。
并且這個(gè)方法執(zhí)行以后,之前pageViewController里的控制器將被釋放,所以pageViewController.viewControllers同樣只裝了1個(gè)viewController。
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController {
//返回即將顯示的控制器
BookTextController *vc = [BookTextController new];
return vc;
}
還有一個(gè)非常有用的代理,它在動(dòng)畫執(zhí)行完畢后被調(diào)用,在controller切換完成后,我們可以在這個(gè)代理中進(jìn)行一些后續(xù)操作。例如用UIPageViewController實(shí)現(xiàn)輪播分頁(yè)等功能。
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray*)previousViewControllers transitionCompleted:(BOOL)completed;
到這里pageViewController的基本使用已經(jīng)差不多了。通過(guò)合理的設(shè)置,我們很容易就可以實(shí)現(xiàn)一個(gè)翻頁(yè)效果。但是在開(kāi)發(fā)閱讀軟件中我還遇到一個(gè)非常嚴(yán)重的體驗(yàn)問(wèn)題。在翻頁(yè)的時(shí)候,書頁(yè)背面的顏色默認(rèn)為白色。在黑夜模式中非常“辣眼睛”!
。
3.解決翻頁(yè)模式書頁(yè)背面“辣眼睛”->doubleSided
顧名思義,doubleSided這個(gè)屬性開(kāi)啟后,書頁(yè)的正反兩面都將顯示文本。
開(kāi)啟這個(gè)屬性后,dataSource中的那兩個(gè)方法會(huì)執(zhí)行2次。
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;
第一次執(zhí)行viewController和之前一樣是正在翻動(dòng)的書頁(yè)的正面,第二次執(zhí)行時(shí)viewController則是第一次return出去的ViewController,即翻動(dòng)書頁(yè)的背面。這樣就會(huì)導(dǎo)致一個(gè)非常嚴(yán)重的問(wèn)題,書頁(yè)正面頁(yè)碼不連續(xù)!“消失”的那一頁(yè)顯示在了上一頁(yè)背面
那么,如何來(lái)優(yōu)化這個(gè)問(wèn)題呢?方法非常簡(jiǎn)單,我們?cè)賱?chuàng)建一個(gè)BackViewController(這里參考了github上一個(gè)demo:
https://github.com/mattabras/DoubleSidedPageViewController
BackViewController源碼可以直接去上面下載。)
BackViewController上只有一個(gè)大小為屏幕大小的UIImageView,在第一次進(jìn)入時(shí),將參數(shù)viewController的view作為圖片設(shè)置到BackViewController的UIImageView里。返回給pageViewController。第二次才返回要顯示的viewController。
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController {
/**
* backviewcontroller->截屏當(dāng)前控制器view,顯示在當(dāng)前頁(yè)背面
*/
if([viewController isKindOfClass:[BookTextController class]]) {
self.currentViewController = viewController;
LZBackViewController *backViewController = [LZBackViewController new];
[backViewController updateWithViewController:viewController];
return backViewController;
}
/**
* 重新加載新的一章或一頁(yè)到lzbooktextcontroller上 并返回給pageviewcontroller
*/
LZBackViewController *showVc = (LZBackViewController *)self.currentViewController;
return showVc;
}
到這里我們解決了黑夜模式書頁(yè)背面辣眼睛的體驗(yàn)問(wèn)題了。
小結(jié)
使用UIPageViewController主要就是理解其層次結(jié)構(gòu)和代理方法調(diào)用時(shí)機(jī)。作為容器加載各式各樣的顯示控制器。在此特別感謝一起開(kāi)發(fā)閱讀APP的戰(zhàn)友小明同學(xué) @GeekDmm 提供的豐富資料。
希望這篇文章可以幫到你。