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页将显示出来。从右到左滑动屏幕,将翻到下一页,做相反方向滑动则翻到上一页。
iOS 5 :一个UIPageViewController程序示例的更多相关文章
- 第一个Mybatis程序示例 Mybatis简介(一)
在JDBC小结中(可以参阅本人JDBC系列文章),介绍到了ORM,其中Mybatis就是一个不错的ORM框架 MyBatis由iBatis演化而来 iBATIS一词来源于“internet”和“aba ...
- 第一个Java程序示例——Hello World!【转】
本文转载自: 跟随世界潮流,第一个Java程序输出“Hell World!”. 通过Eclipse运行程序 启动Eclipse,在菜单中选择“文件 --> 新建 --> Java项目”,弹 ...
- 我的第一个Mybatis程序
第一个Mybatis程序 在JDBC小结中(可以参阅本人JDBC系列文章),介绍到了ORM,其中Mybatis就是一个不错的ORM框架 MyBatis由iBatis演化而来 iBATIS一词来源于“i ...
- Arduino 入门程序示例之一个 LED(2015-06-11)
前言 答应了群主写一些示例程序,一直拖延拖延拖延唉.主要还是害怕在各大高手面前班门弄斧……(这也算是给拖延症找一个美好的理由吧),这几天终于下决心要写出来了,各位高手拍砖敬请轻拍啊. 示例程序 首先是 ...
- 一个简单的JSP程序示例
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...
- IOS开发——01_第一个OC程序
本文目录 一.新建Xcode项目 二.运行项目 注:建议先学习C语言, 如果你还没有编程经验,看不懂的地方可以在评论区提出,本文使用的为Xcode6.1版本,与之前版本会有所差异,但总体不变. 另:还 ...
- 编译运行第一个Java程序——通过示例学习Java编程3
作者:CHAITANYA SINGH 来源:https://www.koofun.com//pro/kfpostsdetail?kfpostsid=13 在本教程中,我们将了解如何编写.编译和运行Ja ...
- iOS开发UI篇—程序启动原理和UIApplication
iOS开发UI篇—程序启动原理和UIApplication 一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就 ...
- iOS开发UI篇—程序启动原理和UIApplication1
iOS开发UI篇—程序启动原理和UIApplication 一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就 ...
随机推荐
- Office.资料
1.JAVA+JS如何在HTML页面上显示WORD文档内容?ActiveX只能兼容IE不考虑!_百度知道.html(https://zhidao.baidu.com/question/74594982 ...
- css tips —— 在css中完成国际化
前提 在日常处理国际化的时候,通常是将key通过类似intl.xx(key)转换为对应环境的文案,可是如果需要在css中加入对应逻辑应该怎么做呢(比如在after的伪元素中显示不同的文案),毕竟在cs ...
- Python面向过程和面向对象基础
总结一下: 面向过程编程:根据业务逻辑从上到下的写代码-----就是一个project写到底,重复利用性比较差 函数式:将某些特定功能代码封装到函数中------方便日后调用 面向对象:对函数进行分类 ...
- 设计模式--观察者模式C++实现
观察者模式C++实现 1定义 Observer/Publish/subscribe发布订阅模式 定义对象间一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖他的对象都能获得通知并被自动更新 2类 ...
- 【Error】2003 - Can't connect to MySQL server on 'localhost' (10038)
此错误主要是连接MySQL地址的地址搞错了. 可以看下 MySQL 的配置文件 /etc/mysql/my.cnf, 其中绑定的本地地址如下: bind-address=127.0.0.1 将其注释掉 ...
- vue elementui二级联动下拉选项demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- mac下csv乱码解决办法
到csv目录下, 用终端执行以下命令: iconv -f UTF8 -t GB18030 a.csv >b.csv
- 最大匹配算法 (Maximum Matching)
之所以研究这个算法,是因为最近在研究NLP中文的分词,所谓分词就是将一个完整的句子,例如“计算语言学课程有意思”,分解成一些词组单元“计算语言学,课程,有,意思”. “最大匹配法” 在中文分词中有所应 ...
- 联想北研实习生面试-嵌入式Linux研发工程师
8月中旬暑假去联想北研参加了实习生面试,面试职位是嵌入式Linux研发工程师.投完简历第二天,主管回复我邮件,意思是说随时来面试,到北研时候给他打个电话就行.于是我回复条短信表示感谢,并约好时间第二天 ...
- JUnit出错,却没有显示任何报错信息【待解答】
JUnit测试代码如下: 原因分析: JUnit测试单元里,测试函数好像不能带参数? 解决办法: 发现测试函数testBookShopDaoUpdateBookStock(int isbn)里的参数i ...