• iOS 5 :一个UIPageViewController程序示例


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

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

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

    创建项目

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

    创建contentViewController

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

    选择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出口。

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

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

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

    创建数据模型

    本例中的数据模型是一个字符串数组。每个字符串是内容不同的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页将显示出来。从右到左滑动屏幕,将翻到下一页,做相反方向滑动则翻到上一页。

  • 相关阅读:
    五种IO模型透彻分析
    linux正则表达式
    洛谷P1242 新汉诺塔 【神奇的递归】
    【NOIP2012】疫情控制
    [ZJOI2007]棋盘制作 【最大同色矩形】
    [NOIP2008]双栈排序 【二分图 + 模拟】
    LCA的倍增算法
    最大权闭合子图
    小Z的袜子 题解报告【莫队】
    ZJOI2012网络 题解报告【LCT】
  • 原文地址:https://www.cnblogs.com/geek6/p/4158052.html
Copyright © 2020-2023  润新知