欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

iOS UIPageViewController使用

程序员文章站 2024-03-23 09:06:52
...

 

UIPageViewController是iOS 5.0之后提供的一个分页控件可以实现图片轮播效果和翻书效果.使用起来简单方便.

一、初始化方法

- (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style
                  navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation
                                options:(nullable NSDictionary<NSString *, id> *)options NS_DESIGNATED_INITIALIZER;

初始化方法三个参数:

※翻转样式枚举

typedef NS_ENUM(NSInteger, UIPageViewControllerTransitionStyle) {

    UIPageViewControllerTransitionStylePageCurl = 0, //翻书效果样式

    UIPageViewControllerTransitionStyleScroll = 1      //滑屏效果样式

};

※滚动方向

typedef NS_ENUM(NSInteger, UIPageViewControllerNavigationOrientation) {

    UIPageViewControllerNavigationOrientationHorizontal = 0, //水平

    UIPageViewControllerNavigationOrientationVertical = 1     //垂直

};

※options:

可选。传入的是对UIPageViewController的配置组成的字典。key可以是:

1、UIPageViewControllerOptionSpineLocationKey(Style为UIPageViewControllerTransitionStylePageCurl时有效), 它定义的是书脊的位置

※书脊位置枚举,决定首页显示的视图个数

typedef NS_ENUM(NSInteger, UIPageViewControllerSpineLocation) {

    UIPageViewControllerSpineLocationNone = 0,  //没有书脊,滚动显示视图

    UIPageViewControllerSpineLocationMin = 1,   // 书脊居左或上,首页显示一个视图

    UIPageViewControllerSpineLocationMid = 2,   // 书脊居中,首页显示两个视图

    UIPageViewControllerSpineLocationMax = 3   // 书脊居右或下,显示一个视图

};  

2、UIPageViewControllerOptionInterPageSpacingKey(Style为UIPageViewControllerTransitionStyleScroll时有效), 它定义的是两个页面之间的间距(默认间距是0).

 

除了初始化方法系统还提供了一个属性:

@property (nonatomic, getter=isDoubleSided) BOOL doubleSided; // Default is 'NO'.

默认为NO,如果我们当前屏幕仅展示一个页面那么不用设置这个属性,如果设置了UIPageViewControllerSpineLocationMid这个选项,效果是翻开的书这样屏幕展示的就是两个页面,这个属性就必须设置为YES了.

此外还有一个重要方法:

- (void)setViewControllers:(nullable NSArray<UIViewController *> *)viewControllers
                 direction:(UIPageViewControllerNavigationDirection)direction
                  animated:(BOOL)animated
                completion:(void (^ __nullable)(BOOL finished))completion;

这个方法是设置UIPageViewController初始显示的页面,如果doubleSided设为YES了,那么viewControllers这个参数至少包含两个页面.

※翻页方式枚举

typedef NS_ENUM(NSInteger, UIPageViewControllerNavigationDirection) {

    UIPageViewControllerNavigationDirectionForward, //从左往右(或从下往上)翻页

    UIPageViewControllerNavigationDirectionReverse  //从右往左(或从上往下)翻页

};  

 

二、数据源和代理:

UIPageViewController类似UITableViewController机制可以设置数据源和代理.

数据源 <UIPageViewControllerDataSource>

iOS SDK提供了四个数据源方法,其中两个为@required,另外两个是@optional.

@required

- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController
               viewControllerBeforeViewController:(UIViewController *)viewController;

这个方法是返回前一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是第一个页面不可以向前滚动或翻页

- (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController
                viewControllerAfterViewController:(UIViewController *)viewController;

这个方法是下一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是最后一个页面不可以向后滚动或翻页

代理 <UIPageViewControllerDelegate>

iOS SDK提供了五个代理方法:

// Sent when a gesture-initiated transition begins.
- (void)pageViewController:(UIPageViewController *)pageViewController
willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers NS_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 __TVOS_PROHIBITED;

这个方法是在style是UIPageViewControllerTransitionStylePageCurl 并且横竖屏状态变化的时候触发,我们可以重新设置书脊的位置,比如如果屏幕是竖屏状态的时候我们就设置书脊位置是UIPageViewControllerSpineLocationMin或UIPageViewControllerSpineLocationMax, 如果屏幕是横屏状态的时候我们可以设置书脊位置是UIPageViewControllerSpineLocationMid

- (UIInterfaceOrientationMask)pageViewControllerSupportedInterfaceOrientations:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
- (UIInterfaceOrientation)pageViewControllerPreferredInterfaceOrientationForPresentation:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;

这两个方法设置了UIPageViewController支持的屏幕类型

 

三、实现效果

翻书效果

直接上代码和效果

ViewController的.m代码如下:

@interface ViewController () <UIPageViewControllerDelegate, UIPageViewControllerDataSource>

@property (nonatomic, strong) UIPageViewController *pageViewController;
@property (nonatomic, strong) NSArray *pageContentArray;

@end

@implementation ViewController

#pragma mark - Lazy Load

- (NSArray *)pageContentArray {
    if (!_pageContentArray) {
        NSMutableArray *arrayM = [[NSMutableArray alloc] init];
        for (int i = 1; i < 10; i++) {
            NSString *contentString = [[NSString alloc] initWithFormat:@"This is the page %d of content displayed using UIPageViewController", i];
            [arrayM addObject:contentString];
        }
        _pageContentArray = [[NSArray alloc] initWithArray:arrayM];

    }
    return _pageContentArray;
}

#pragma mark - Life Cycle

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置UIPageViewController的配置项
//    NSDictionary *options = @{UIPageViewControllerOptionInterPageSpacingKey : @(20)};
    NSDictionary *options = @{UIPageViewControllerOptionSpineLocationKey : @(UIPageViewControllerSpineLocationMin)};

    // 根据给定的属性实例化UIPageViewController
    _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
                                                          navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                                        options:options];
    // 设置UIPageViewController代理和数据源
    _pageViewController.delegate = self;
    _pageViewController.dataSource = self;
    
    // 设置UIPageViewController初始化数据, 将数据放在NSArray里面
    // 如果 options 设置了 UIPageViewControllerSpineLocationMid,注意viewControllers至少包含两个数据,且 doubleSided = YES
    
    ContentViewController *initialViewController = [self viewControllerAtIndex:0];// 得到第一页
    NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
    
    [_pageViewController setViewControllers:viewControllers
                              direction:UIPageViewControllerNavigationDirectionReverse
                               animated:NO
                             completion:nil];

    // 设置UIPageViewController 尺寸
    _pageViewController.view.frame = self.view.bounds;

    // 在页面上,显示UIPageViewController对象的View
    [self addChildViewController:_pageViewController];
    [self.view addSubview:_pageViewController.view];

}

#pragma mark - UIPageViewControllerDataSource And UIPageViewControllerDelegate

#pragma mark 返回上一个ViewController对象

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    
    NSUInteger index = [self indexOfViewController:(ContentViewController *)viewController];
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }
    index--;
    // 返回的ViewController,将被添加到相应的UIPageViewController对象上。
    // UIPageViewController对象会根据UIPageViewControllerDataSource协议方法,自动来维护次序
    // 不用我们去操心每个ViewController的顺序问题
    return [self viewControllerAtIndex:index];
    
    
}

#pragma mark 返回下一个ViewController对象

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    
    NSUInteger index = [self indexOfViewController:(ContentViewController *)viewController];
    if (index == NSNotFound) {
        return nil;
    }
    index++;
    if (index == [self.pageContentArray count]) {
        return nil;
    }
    return [self viewControllerAtIndex:index];
    
    
}

#pragma mark - 根据index得到对应的UIViewController

- (ContentViewController *)viewControllerAtIndex:(NSUInteger)index {
    if (([self.pageContentArray count] == 0) || (index >= [self.pageContentArray count])) {
        return nil;
    }
    // 创建一个新的控制器类,并且分配给相应的数据
    ContentViewController *contentVC = [[ContentViewController alloc] init];
    contentVC.content = [self.pageContentArray objectAtIndex:index];
    return contentVC;
}

#pragma mark - 数组元素值,得到下标值

- (NSUInteger)indexOfViewController:(ContentViewController *)viewController {
    return [self.pageContentArray indexOfObject:viewController.content];
}

@end

ContentViewController的.h代码

@interface ContentViewController : UIViewController

@property (nonatomic, copy) NSString *content;

@end

ContentViewController的.m代码

#define kRandomColor ([UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0f])

@interface ContentViewController ()

@property (nonatomic, strong) UILabel *contentLabel;

@end

@implementation ContentViewController

- (void)viewDidLoad{
    [super viewDidLoad];
    self.view.backgroundColor = kRandomColor;
    _contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, 100)];
    _contentLabel.numberOfLines = 0;
    _contentLabel.backgroundColor = kRandomColor;
    [self.view addSubview:_contentLabel];
}

- (void) viewWillAppear:(BOOL)paramAnimated{
    [super viewWillAppear:paramAnimated];
    _contentLabel.text = _content;
}

@end

翻书效果.gif

iOS UIPageViewController使用

滚动效果

关于滚动效果只需将初始化配置修改一下即可:

 

    // 设置UIPageViewController的配置项
    NSDictionary *options = @{UIPageViewControllerOptionInterPageSpacingKey : @(20)};
//    NSDictionary *options = @{UIPageViewControllerOptionSpineLocationKey : @(UIPageViewControllerSpineLocationMin)};

    // 根据给定的属性实例化UIPageViewController
    _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
                                                          navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
                                                                        options:options];

滚动效果.gif

iOS UIPageViewController使用

作者:herbsun
链接:https://www.jianshu.com/p/46c8c585d50b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关标签: iOS UIKit框架