iOS UIPageViewController - 使用总结

最近在一个项目中需要一种以翻书的形式来展示图片的功能,在查阅了一些资料后,初步了解了UIPageViewController,查到的资料都是比较久之前的,有的还是在MRC的,在使用的过程中也遇到一些问题,最终磕磕绊绊也算是实现了这个功能,现将使用的一些积累整理一下,也算是一种记录吧.其中借用了一些网上的代码段,如有雷同,感谢分享!!

本文只介绍简单的使用,只针对初次使用UIPageViewController,高手请绕行!

理论的介绍及更深入的功能请自行查阅相关资料!

UIPageViewController主要是一个实现类似翻书的效果的控件,其中主要用到了它的两个数据源方法:

//返回前一个视图
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController

//返回下一个视图
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController

需要先导入数据源代理

UIPageViewControllerDataSource
下面初始化UIPageViewController,在初始化的时候传入的options中,可以选择是单页显示,还是双页显示

// UIPageViewControllerSpineLocationMin 单页显示
     
// UIPageViewControllerSpineLocationMid 双页显示

NSDictionary * options = [NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMid] forKey:UIPageViewControllerOptionSpineLocationKey];
    
self.LQQ_pageViewController = [[UIPageViewController alloc]initWithTransitionStyle:(UIPageViewControllerTransitionStylePageCurl) navigationOrientation:(UIPageViewControllerNavigationOrientationHorizontal) options:options];
设置数据源代理

self.LQQ_pageViewController.dataSource = self;
获取数据源视图,因为我的是双页显示的,所以先获取两页,如果是单页,先初始化获取一个就行

LQQContentViewController * initialViewController = [self viewCintrollerAtIndex:0];
LQQContentViewController * endViewController = [self viewCintrollerAtIndex:1];

将数据源数组赋值给UIPageViewController:

NSArray * viewControllers = [NSArray arrayWithObjects:initialViewController,endViewController,nil];
    
[self.LQQ_pageViewController setViewControllers:viewControllers direction:(UIPageViewControllerNavigationDirectionForward) animated:NO completion:nil];
添加视图:

[self addChildViewController:self.LQQ_pageViewController];
[self.view addSubview:self.LQQ_pageViewController.view];
[self.LQQ_pageViewController didMoveToParentViewController:self];
以上这些可以直接使用,基本不会有多大变化,下面这个是设置 UIPageViewController的frame,

这个可根据自己需求设定,因为我的是横屏显示的,没有做转屏,而是让竖图旋转了90°:

self.LQQ_pageViewController.view.center = CGPointMake(self.view.center.x, self.view.center.y + 32);
self.LQQ_pageViewController.view.bounds = CGRectMake(0, 0, self.view.frame.size.height - 104, self.view.frame.size.width - 20);
self.LQQ_pageViewController.view.transform = CGAffineTransformMakeRotation(M_PI_2);
这样 UIPageViewController的初始化基本就完成了!

因为要多次调用创建数据源视图(这里是LQQContentViewController),所以单独写成一个方法:

//返回一个视图
- (LQQContentViewController *)viewCintrollerAtIndex:(NSUInteger)index
{
    if ([self.LQQ_pageContent count] == 0 || (index >= [self.LQQ_pageContent count]))
    {
        return nil;
    }
    
    LQQContentViewController * dataViewController = [[LQQContentViewController alloc]init];
    
    //如果去掉这个if-else 照片无法正常显示,原因暂不明确
    if (index == 0 || index == self.LQQ_pageContent.count - 1)
    {
#warning 如果不需要显示第一页和最后一页,就将第一页的背景色与viewController一致,或者隐藏掉,这样才会有看到书的封面和封底的效果
        dataViewController.view.backgroundColor = [UIColor greenColor];
    }
    else
    {
#warning 其他页的一些设置,即使不需要设置什么,也要随机设置个背景色或者其他属性,否则会显示不正常
        dataViewController.view.backgroundColor = [UIColor purpleColor];
    }

#warning -- 配置数据源
    dataViewController.LQQ_imageView.image = [self.LQQ_pageContent objectAtIndex:index];
    
    //这句必须有,且只能这么写
    dataViewController.LQQ_dataObject = [self.LQQ_pageContent objectAtIndex:index];
    
    return dataViewController;
}

为需要展示的视图配置数据也在上面这个方法里;

方法中的LQQ_dataObject属性主要是用于返回当前视图在数据源中的index值的:

//获取当前页的索引
- (NSUInteger)indexOfViewController:(LQQContentViewController*)viewController
{
    return  [self.LQQ_pageContent indexOfObject:viewController.LQQ_dataObject];
}

下面只需实现他的两个数据源方法:

#pragma mark -- UIPageViewController 数据源方法
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(LQQContentViewController *)viewController];
    if (index == 0 || (index == NSNotFound)) {
        return nil;
    }
    index --;
    return [self viewCintrollerAtIndex:index];
}
- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(LQQContentViewController *)viewController];
    if (index == NSNotFound) {
        return nil;
    }
    index++;
    if (index == [self.LQQ_pageContent count]) {
        return nil;
    }
    return [self viewCintrollerAtIndex:index];
}

最后给出我定义的展示视图,因为我用的是xib创建的,只是在.h文件中关联一下,如果不用xib,使用代码创建,本人尝试过直接设置frame,这样在现实的额时候并没有按照预想的显示,如果只是在xib中添加了控件而没有添加约束,也不能实现;

个人认为是必须要约束其子视图的位置,而不能只是设置其坐标,这块没有深入理解,所以可以选择使用xib,并添加约束;也可以代码创建,添加约束!

#import <UIKit/UIKit.h>

@interface LQQContentViewController : UIViewController

/**
 *  @author LQQ, 15-12-26 18:12:19
 *
 *  这个属性主要是用于返回创建的对象在数据源数组中的索引,不属于显示的内容,但是必须要有
 */
@property (retain,nonatomic)id LQQ_dataObject;

/**
 *  @author LQQ, 15-12-26 18:12:51
 *
 *  自定义布局的内容
 */
@property (weak, nonatomic) IBOutlet UIImageView *LQQ_imageView;
//@property (nonatomic,weak)IBOutlet UIImage *LQQ_image;
@end

最后附上完整Demo: UIPageController简单使用


另外,UIPageViewController也有代理方法,具体的使用请自行参照API!

你可能感兴趣的:(ios,翻页,翻书)