用UIPageViewController 实现翻页效果

原文:http://www.techotopia.com/index.php/An_Example_iOS_5_iPhone_UIPageViewController_Applicationphp

在Xcode中新建项目时,能够选择“Page-based Application”项目模板。能够利用这个模板建立一种“基于页”的应用程序,在1年的每月中显示不一样的页。奇怪的是,这是Xcode提供的惟一一个基于实例的模板而不是应用程序基本框架。这对于一开始学习时颇有用,但除非你真的须要一个用12页来显示1年不一样月份的程序,不然你必需从这个模板中移除一些已有的东西,以用于其余目的。html

实际上,除了使用Xcode’s的“Page-based Application”模板,咱们也可使用Single View Application 模板,只不过本身须要实现Page-based的行为。这有两方面的好处。首先,不使用Page-base模板能使咱们更能理解UIPageViewController的实现细节。其次,这种方式也比去修改Page-based Application模板要更加简捷。web

建立项目

启动Xcode,新建iOS single view application项目,确认不要使用Use Storyboard选项。数组

建立contentViewController

本示例使用单个View Controller实例显示多个页。视图中包含了一个UIWebView,根据当前选择的页显示不一样Html内容。ViewController类有一个data对象属性用于持有视图的Html。app

选择FileàNewàNewFile…菜单,新建UIViewController subclass,名为contentViewController(勾选“With XIB…”选项)。打开contentViewController.h,为webview对象和data对象添加出口并进行链接。框架

#import <UIKit/UIKit.h>
@interface contentViewController : UIViewController 
@property (strong, nonatomic) IBOutlet UIWebView *webView; 
@property (strong, nonatomic) id dataObject; 
@end 

而后,打开contentViewController.xib,拖一个UIWebView组件到view上:学习

 

右键从File’s Owner 拖一条链接线到web view对象并选择webView出口。ui

编辑contentViewController.m文件。每当用户翻页时,UIPageViewController的数据源方法会建立一个新的contentViewController实例而后设置其dataObject属性为相应的Html。而在contentViewController的viewWillAppear方法中,咱们会将dataObject属性赋给webview对象。为此,咱们加入了必要的@synthesize语句,同时修改了viewWillAppear方法:atom

#import "contentViewController.h"  
@implementation contentViewController 
@synthesize webView, dataObject; 
. 
. 
- (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
     [webView loadHTMLString:dataObject
         baseURL:[NSURL URLWithString:@""]]; 
} 
. 
. 
@end 

接下来,咱们来实现数据模型。url

建立数据模型

本例中的数据模型是一个字符串数组。每一个字符串是内容不一样的Html内容。pageAppViewController类就是UIPageViewController对象的数据源。该类含有一个NSArry和一个UIPageViewController对象,同时实现UIPageViewcontrollerDataSource协议。打开pageAppViewController.h,导入contentViewController.h头文件,加入必要的声明:

 

#import <UIKit/UIKit.h> 
#import “contentViewController.h”  
@interface pageAppViewController : UIViewController <UIPageViewControllerDataSource> {
     UIPageViewController *pageController;
     NSArray *pageContent; 
} 
@property (strong, nonatomic) UIPageViewController *pageController; 
@property (strong, nonatomic) NSArray *pageContent; 
@end 

最后,在pageAppViewController.m中增长一个方法以把Html字符串加到数组中。而后在viewDidLoad方法中调用这个方法。

 
#import "pageAppViewController.h"  
@implementation pageAppViewController 
@synthesize pageController, pageContent;
 .
 . 
- (void) createContentPages {
     NSMutableArray *pageStrings = [[NSMutableArray alloc] init];
     for (int i = 1; i < 11; i++)
     {
         NSString *contentString = [[NSString alloc]
 initWithFormat:@"<html><head></head><body><h1>Chapter %d</h1><p>This is the page %d of content displayed using UIPageViewController in iOS 5.</p></body></html>", i, i];
         [pageStrings addObject:contentString];
     }
     pageContent = [[NSArray alloc] initWithArray:pageStrings]; 
}
 .
 . 
- (void)viewDidLoad {
     [super viewDidLoad];
     [self createContentPages]; 
} 
 

如今,咱们已经有一个content view controller和一个data model了,data model将经过数据源方法来提取每一页的内容。下一步,就是实现这些数据源方法。如“Implementinga Page based iOS 5 iPhone Application using UIPageViewController”中所述, UIPageViewController 实例须要一个数据源,数据源方法有两个,一个是返回当前显示的view controller以后的view controller,而另外一个是返回当前显示的view controller以前的viewcontroller。因为pageAppViewController扮演了page view controller的数据源,所以须要在pageAppViewController.m中加入这两个方法(以及另外两个便利方法)。首先咱们来看这2个便利方法:

 

#import "pageAppViewController.h"  
@implementation pageAppViewController 
@synthesize pageController, pageContent;  
- (contentViewController *)viewControllerAtIndex:(NSUInteger)index {
     // Return the data view controller for the given index.
     if (([self.pageContent count] == 0) || 
             (index >= [self.pageContent count])) {
         return nil;
     }
      // Create a new view controller and pass suitable data.
     contentViewController *dataViewController = 
         [[contentViewController alloc]
         initWithNibName:@"contentViewController" 
         bundle:nil];
     dataViewController.dataObject =
        [self.pageContent objectAtIndex:index];
     return dataViewController; 
- (NSUInteger)indexOfViewController:(contentViewController *)viewController {
      return [self.pageContent 
indexOfObject:viewController.dataObject]; 
}
 .
 . 
@end 

 

viewControllerAtIndex: 方法首先检查有效页数是否<0(用户不可能回到第1页之前)或者要检索的页数已经超出了pageContent数组的实际数目。若是index参数有效,就建立一个新的contentViewController实例并将dataObject属性设置为相应的pageContent条目(Html字串)。

 indexOfViewController 方法指定一个viewController做为参数,并返回这个viewController的索引。它使用viewcontroller的dataObject属性去在pageContent数组元素中检索其索引

如今来看两个数据源方法。它们使用这两个便利方法返回当前view  controller“以前”和“以后”的view  controller:

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

下一步,就是建立和实例化UIPageViewController类。

 

实例化UIPageViewController

接下来就是建立UIPageViewController实例并初始化。用于这个过程只须要进行一次,所以把代码写在pageAppViewController的viewDidLoad方法中就能够了。打开pageAppViewController.m 文件修改 viewDidLoad:

 

- (void)viewDidLoad {
     [super viewDidLoad];
     [self createContentPages];
     NSDictionary *options =
       [NSDictionary dictionaryWithObject:
      [NSNumber
 numberWithInteger:UIPageViewControllerSpineLocationMin]
      forKey: UIPageViewControllerOptionSpineLocationKey];
      self.pageController = [[UIPageViewController alloc]         initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl   navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
        options: options];
      pageController.dataSource = self;
     [[pageController view] setFrame:[[self view] bounds]];
      contentViewController *initialViewController =
         [self viewControllerAtIndex:0];
     NSArray *viewControllers =
          [NSArray arrayWithObject:initialViewController];     
     [pageController setViewControllers:viewControllers
         direction:UIPageViewControllerNavigationDirectionForward
        animated:NO
        completion:nil];
      [self addChildViewController:pageController];
     [[self view] addSubview:[pageController view]];
     [pageController didMoveToParentViewController:self]; 
} 

 

所有代码到此结束。在编译和运行程序以前,咱们先分析一下viewDidLoad方法中的代码。

构建数据模型以后,咱们建立了一个NSDictionary对象。这个NSDictionary中包含了一个options,用于page controrller对象的初始化选项。在这里,该选项指定了spine位于屏幕左侧(spine即书脊,书页装订的位置,书从另外一侧翻阅):

 

NSDictionary *options =     [NSDictionary dictionaryWithObject:     [NSNumber numberWithInteger:UIPageViewControllerSpineLocationMin]     forKey: UIPageViewControllerOptionSpineLocationKey]; 
 

下一句,用前面的options实例化UIPageViewController:

 
self.pageController = [[UIPageViewController alloc]    initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl   navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal   options: options]; 
 
要让类成为page controller的数据源,还要作一些配置。好比咱们要让页面全屏,须要设置它的frame:
 
pageController.dataSource = self; 
[[pageController view] setFrame:[[self view] bounds]]; 
 
 

在第1页能显示以前,咱们首先须要建立一个view controller。这能够调用 viewControllerAtIndex: 便利方法。 在得到一个contentview controller后,把它放到一个数组对象中:

 
contentViewController *initialViewController =
     [self viewControllerAtIndex:0]; 
NSArray *viewControllers =
      [NSArray arrayWithObject:initialViewController]; 

 

注意,只须要一个content view controller。由于page controller被设定为一次只显示1页(单面)。若是将pagecontroller配置为2页(spine位于中央)或者双面,则须要建立2个content view controller并放入数组。

而后,将数组对象赋给view controller并将导航方向设置为向前模式:

 
[pageController setViewControllers:viewControllers
      direction:UIPageViewControllerNavigationDirectionForward
     animated:NO
     completion:nil]; 
 

最后,将page vview controller加到当前视图:

 
[self addChildViewController:pageController];
 [[self view] addSubview:[pageController view]];
 [pageController didMoveToParentViewController:self]; 

 

运行 UIPageVIewController 应用

点击Run,运行程序。第1页将显示出来。从右到左滑动屏幕,将翻到下一页,作相反方向滑动则翻到上一页。

相关文章
相关标签/搜索