UIPageViewController看这篇就够了
先说初始化
- (UIPageViewController *)PageViewController{
if(!_PageViewController){
//书脊位置,只有在UIPageViewControllerTransitionStylePageCurl才生效
NSDictionary *options =[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMin]
forKey: UIPageViewControllerOptionSpineLocationKey];
//两个page之间的间距,只有UIPageViewControllerTransitionStyleScroll格式才生效
// NSDictionary *options =[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:0]
// forKey: UIPageViewControllerOptionInterPageSpacingKey];
_PageViewController = [[ UIPageViewController alloc]initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:options];
_PageViewController.view.backgroundColor = [UIColor clearColor];
_PageViewController.dataSource = self;
_PageViewController.delegate = self;
}
return _PageViewController;
}
然后填充内容
//填充PageView
- (void)setPageViewData{
[self.controllerArray removeAllObjects];
ReadingSubViewController *subView = [self viewControllerAtIndex:0];
[self.controllerArray addObject:subView];
[self.PageViewController setViewControllers:self.controllerArray direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) {
}];
} - (ReadingSubViewController *)viewControllerAtIndex:(NSInteger)index{
NSLog(@"push%ld",index);
ReadingSubViewController *subView = [[ReadingSubViewController alloc]init];
subView.pageModel = self.bookpageData[index];
subView.bookModel = self.model;
subView.pageIndex = index;
_open = YES;
[self pushButtonClick];
return subView;
}
&&重点
重点是是他内部的运行逻辑,我也是今天才完全搞清楚。
先看delegate
#pragma mark ==========PageVCDelegate==========
//这个方法是返回前一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是第一个页面不可以向前滚动或翻页
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
NSInteger index = [self getIndex:(ReadingSubViewController *)viewController];
NSLog(@"before=%ld",index);
if (index == 0 || index == NSNotFound) {
return nil;
}
index -- ;
ReadingSubViewController *playVC = [self viewControllerAtIndex:index];
if (index+1< 10) {
self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",index+1,_maxPage];
}else{
self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",index+1,_maxPage];
}
return playVC;
}
//这个方法是下一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是最后一个页面不可以向后滚动或翻页
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
NSInteger index = [self getIndex:(ReadingSubViewController *)viewController];
if (index == NSNotFound || index == _maxPage - 1) {
return nil;
}
NSLog(@"after=%ld",index);
index ++;
ReadingSubViewController *playVC = [self viewControllerAtIndex:index];
if (index+1< 10) {
self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",index+1,_maxPage];
}else{
self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",index+1,_maxPage];
}
return playVC;
}
- (NSInteger)getIndex:(ReadingSubViewController *)subVC{
return subVC.pageIndex;
}
如果TransitionStyle是UIPageViewControllerTransitionStylePageCurl
那么从首页开始拖动的时候,往左拖动,会触发viewControllerBeforeViewController这个代理方法,并不会触发viewControllerAfterViewController代理方法。
然后每次往右拖动时只会加载一个ViewController。上面整个流程的Log如下
eadingViewController.m[88] push0
ReadingViewController.m[102] before=0
ReadingViewController.m[121] after=0
ReadingViewController.m[88] push1
ReadingViewController.m[136] 开始滚动
ReadingViewController.m[140] isCompleted:成功
ReadingViewController.m[121] after=1
ReadingViewController.m[88] push2
ReadingViewController.m[136] 开始滚动
ReadingViewController.m[140] isCompleted:成功
如果TransitionStyle是UIPageViewControllerTransitionStyleScroll
那么从首页开始拖动,不管是往右还是往左,都肯定会viewControllerAfterViewController,为PageController加载好下个Page的ViewController。我往左拖动的Log如下
ReadingViewController.m[88] push0
ReadingViewController.m[102] before=0
ReadingViewController.m[121] after=0
ReadingViewController.m[88] push1
虽然拖动完成的代理方法没有执行。但是 viewControllerAfterViewController方法触发,加载好了下一页的ViewController内容。
然后往右拖动会提前加载第三页的内容Log如下
ReadingViewController.m[102] before=0
ReadingViewController.m[121] after=0
ReadingViewController.m[88] push1
ReadingViewController.m[136] 开始滚动
ReadingViewController.m[140] isCompleted:成功
ReadingViewController.m[121] after=1
ReadingViewController.m[88] push2
如果是开始就往右拖动的话Log如下
ReadingViewController.m[88] push0
ReadingViewController.m[121] after=0
ReadingViewController.m[88] push1
ReadingViewController.m[102] before=0
ReadingViewController.m[136] 开始滚动
ReadingViewController.m[140] isCompleted:成功
ReadingViewController.m[121] after=1
ReadingViewController.m[88] push2
ReadingViewController.m[136] 开始滚动
ReadingViewController.m[140] isCompleted:成功
ReadingViewController.m[121] after=2
ReadingViewController.m[88] push3
这是拖动到第三页的时候,但是第四页其实已经预加载好了。
之前一直没有用过UIPageViewControllerTransitionStyleScroll,今天用了一次才发现自己认识的很不清晰。做下记录
更新!
前面关于self.pageNumberLB.text,也就是当前页码的写法,如果是在UIPageViewControllerTransitionStylePageCurl格式下是没有问题的。但是如果是在UIPageViewControllerTransitionStyleScroll格式下。因为会有一个预加载,viewControllerAfterViewController会调用两次。所以会造成有误!
解决方法:还有两个协议方法
//这个方法是UIPageViewController开始滚动或翻页的时候触发
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers{
ReadingSubViewController *firstVC =(ReadingSubViewController *) pendingViewControllers.firstObject;
NSInteger index = firstVC.pageIndex;
NSLog(@"开始滚动%ld",index);
_animationIndex = index; }
//这个方法是在UIPageViewController结束滚动或翻页的时候触发
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed{
NSLog(@"isCompleted:%@",completed?@"成功":@"失败");
if (completed) {
if (_animationIndex+< ) {
self.pageNumberLB.text = [NSString stringWithFormat:@"0%ld/%ld",_animationIndex+,_maxPage];
}else{
self.pageNumberLB.text = [NSString stringWithFormat:@"%ld/%ld",_animationIndex+,_maxPage];
}
} }
其实只用上面那个就可以基本满足,不过会有轻微的拖动一下虽然没有翻页成功也会改变页码字符的现象,配合下方的方法就完美了。
OVER
2019-10-31更新
最近一个项目也用到了PageViewController,开始是UIPageViewControllerTransitionStylePageCurl,后来想用UIPageViewControllerTransitionStyleScroll,发现坑太多了,改成了UICollectionView去代替。
如果style是UIPageViewControllerTransitionStyleScroll,不推荐用PageViewController,坑太多了!!
UIPageViewController看这篇就够了的更多相关文章
- ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必是件很痛苦的事情吧,但文档又必须写,而且文档的格式如果没有具体要求的话,最终完成的文档则完全取决于开发者 ...
- .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了
作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9985451.html 本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新 ...
- 想了解SAW,BAW,FBAR滤波器的原理?看这篇就够了!
想了解SAW,BAW,FBAR滤波器的原理?看这篇就够了! 很多通信系统发展到某种程度都会有小型化的趋势.一方面小型化可以让系统更加轻便和有效,另一方面,日益发展的IC**技术可以用更低的成本生产 ...
- [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了
[译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 本文首发自:博客园 文章地址: https://www.cnblogs.com/yilezhu/p/ ...
- ExpandoObject与DynamicObject的使用 RabbitMQ与.net core(一)安装 RabbitMQ与.net core(二)Producer与Exchange ASP.NET Core 2.1 : 十五.图解路由(2.1 or earler) .NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了
ExpandoObject与DynamicObject的使用 using ImpromptuInterface; using System; using System.Dynamic; names ...
- Vue学习看这篇就够
Vue -渐进式JavaScript框架 介绍 vue 中文网 vue github Vue.js 是一套构建用户界面(UI)的渐进式JavaScript框架 库和框架的区别 我们所说的前端框架与库的 ...
- 【转】ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了
原文链接:https://www.cnblogs.com/yilezhu/p/9241261.html 引言 在使用asp.net core 进行api开发完成后,书写api说明文档对于程序员来说想必 ...
- Pycharm新手教程,只需要看这篇就够了
pycharm是一款高效的python IDE工具,它非常强大,且可以跨平台,是新手首选工具!下面我给第一次使用这款软件的朋友做一个简单的使用教程,希望能给你带来帮助! 目前pycharm一共有两个版 ...
- Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) JAVA日志的前世今生 .NET MVC采用SignalR更新在线用户数 C#多线程编程系列(五)- 使用任务并行库 C#多线程编程系列(三)- 线程同步 C#多线程编程系列(二)- 线程基础 C#多线程编程系列(一)- 简介
Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) 一.前言 由于本篇文章较长,所以下面给出内容目录方便跳转阅读,当然也可以用博客页面最右侧的文章目录导航栏进行跳转查阅. 一.前言 ...
随机推荐
- 聊聊redis实际运用及骚操作
前言 聊起 redis 咱们大部分后端猿应该都不陌生,或多或少都用过.甚至大部分前端猿都知道. 数据结构: string. hash. list. set (无序集合). setsorted(有序集合 ...
- Guava之controller中使用缓存cache
之前介绍过的Guava这个工具包中有很多方便的用法,下面要使用它封装的Cache来实现功能. 示例: import com.google.common.cache.CacheBuilder; impo ...
- MES training
unique identity 1.project name , namespace 2. select XML (not html) 3. view and controller will be i ...
- vue $attrs 父组件和孙子组件的传值,传函数
上一篇我们说到provide/inject的依赖注入的传值方法,今天我们来说一下另一个父组件给孙子组件的传值方式$attrs 我们接着上一个例子继续来写 parent父组件 我们给child子组件穿了 ...
- CSS3 新特性(box-sizing盒模型,背景线性渐变,filter滤镜,calc函数,transition过渡)
1.盒子模型(box-sizing) CSS3 中可以通过 box-sizing 来指定盒模型,有两个值:即可指定为 content-box.border-box,这样我们计算盒子大小的方式就发生了改 ...
- 使用TPL取回Task中的运行结果的三种方式
概念:TPL( Task Parallel Library) 任务并行库 使用Task类执行多线程操作要比直接使用自己手工创建Thread效率高很多. 默认情况下,TPL使用线程池中的线程执行Task ...
- 2019-8-31-How-to-use-code-to-exit-the-application-in-UWP
title author date CreateTime categories How to use code to exit the application in UWP lindexi 2019- ...
- 2018-8-10-win10-uwp-ApplicationView
title author date CreateTime categories win10 uwp ApplicationView lindexi 2018-08-10 19:16:53 +0800 ...
- 同域SQL server 做镜像服务器遇到1418错误
今天遇到了如题所说的错误,查了一天没有看到好的解决方案,因为作者是小白,所以对于解决方案都是代码的那种,完全理解不了. 现在,讲述一下我的解决方法.因为是同域的服务器,这个时候说网络访问不了对方,但是 ...
- rabbitmq使用延迟时报异常
声明交换机为延迟时报异常( unknown exchange type 'x-delayed-message')的解决方法 服务端需下载安装插件: 1.下载插件包 2.将下载后的插件包移至服务安装目录 ...