声明:本文翻译自AppCoda网站的文章:How To Create UIPageViewController Using Storyboard,如有异议,请联系博主。
之前我们已经讲过UIPageViewController,那篇文章演示了如何使用Interface Builder创建UIPageViewController。为了适配iOS7和Xcode5,我们重新写了这篇新教程——使用Storyboard创建UIPageViewController。
你第一次打开一个app的时候,一定会发现一系列的引导页(或者是操作指南)来给你介绍一些这个app的特性,这是给用户介绍app功能的通常做法。这篇文章中,我们就来看看如何用UIPageViewController创建一个类似的引导页面。
UIPageViewController在iOS 5 SDK中首次引入,它使得开发者可以使用这个ViewController创建分页视图。在iOS 6中,这个类有了更新,支持滚动过渡效果。使用Page View,用户可以方便的通过手势在多个页面之间导航。UIPageViewController并不仅仅用于引导页,很多游戏,例如:愤怒的小鸟,就是用Page View来展示关卡选择的页面,还有有关书籍的应用,用这个类来显示书的页面。
[caption id=”” align=”aligncenter” width=”800” class=” “]example[/caption]
UIPageViewController是个高度可配置的类,你可以进行如下配置:
- 分页的方向——水平或垂直
- 翻页的样式——书卷翻页或者滑动翻页
- 书脊位置——只有书卷翻页样式有效
- 页面间距——只有滑动翻页样式有效,用来定义页面间距(inter-page spacing)
为了演示,我们会一起创建一个简单的app。当然,我们不会演示所有的UIPageViewController的配置细节,我们会演示到使用滑动翻页样式来创建一个引导页。不过别担心,有了对UIPageViewController的基本理解,我相信你能够去探索其他的特性。
开始吧!
Demo一览
我们要创建的Demo很简单,它会显示4个页面来介绍app的UI。用户可以在页面之间滑动切换。在任何时候用户点击“Start again”按钮会回到第一页。你能在Snapguide或Airbnb等app中找到很多类似的引导页,所以这个效果你应该不陌生。
创建项目
打开Xcode并创建一个Simple View Application项目。选择Single View Application看起来有点奇怪,因为Xcode已经提供了基于UIPageViewController的具有完整功能的Page-Based Application模板。但是,这个模板还是有一些复杂,把这个模板解释清楚比重新开始一个项目要复杂的多。况且,从零开始一定会让我们对UIPageViewController的使用有更好的掌握。
好了,开始吧。下个页面中输入PageViewDemo作为项目名称,在company identifier栏中填入com.appcoda,设备类型选择iPhone。点击下一步并创建项目。
在Storyboard中创建Page View Controller
下一步,选择Main.storyboard。通常,你会看到一个默认的由Xcode生成的View Controller,先别管它,从Object Library拖出一个Page View Controller到Storyboard中。然后再拖出另一个View Controller。
在这个项目中,第一个View Controller会作为根View Controller,承载Page View Controller。最后添加的View Controller会作为页面的内容。后文中,用“根VC”代表“第一个View Controller”,“内容VC”代表“最后添加的View Controller”。
你可能会疑惑为什么只添加1个View Controller作为4页的内容,难道不应该使用4个View Controller吗?通过后面的演示你会发现,引导页都非常相似,通过复用这个View Controller显然是更好的选择。
下一步,给内容VC和Page View Controller分别设置一个ID。你能在Identity Inspector面板方便地设置。将Page View Controller的ID设置为“PageViewController”,将内容VC的ID设置为“PageContentController”。后面我们会在代码中使用到这些ID。
Page View Controller的默认变换样式是翻页效果(Page Curl),这个效果比较适合书籍类应用。引导页中,使用滑动效果更合适,所以将transition style更改为Scroll。
现在来设计内容vc的界面。拖出一个Image View和一个Label到Controller中。按照喜好更改字体和字号。但是你的View Controller应该和下面截图的样子类似。
对于那个默认的View Controller,在底部添加一个“Start again”按钮。
编写View Controller类
下一步是编写View Controller类并和对应的View Controller绑定。在菜单栏中选择File -> New -> File… 之后选择“Objective-C class”模板。命名为PageContentViewController,并使这个类继承自UIViewController。
返回Storyboard,选择内容VC并在Identify Inspector中设置Custom Class项为PageContentViewController。
下一步,我们为Image View和Label创建outlet。切换到(辅助编辑)Assistant Editor模式并确保PageContentViewController.h文件已经打开。按住Control键从Image View拖动到PageContentViewController.h创建IBOutlet。设置名字分别为backgroundImageView和titleLabel。
经过上面的编辑,PageContentViewController.h文件应该像下面这样:
1 2 3 4 5 6 7 | #import <UIKit/UIKit.h> @interface PageContentViewController : UIViewController @property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView; @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @end |
下一步,选择根VC并确保ViewController.h已经打开了。创建从“Start again”按钮的action,命名为“startWalkthrough”。
好了,我们已经完成了UI的设计,并已经创建好了outlet,开始实现View Controller类吧。
实现Page Content View Controller
实现PageContentViewController非常简单第一步,像PageContentViewController.h中添加以下属性:
1 2 3 | @property NSUInteger pageIndex; @property NSString *titleText; @property NSString *imageFile; |
pageIndex属性用来储存当前页面的索引(位置)。因为这个View Controller用来显示一张图片和一个标题,所以我们创建两个属性分别用来接收titleText和imageFile。下一步,打开PageContentViewController.m,将viewDidLoad:方法修改成这样:
1 2 3 4 5 6 7 | - (void)viewDidLoad { [super viewDidLoad]; self.backgroundImageView.image = [UIImage imageNamed:self.imageFile]; self.titleLabel.text = self.titleText; } |
实现Page View Controller
UIPageViewController的定位是Controller的容器。这个容器用来包含和管理要在app中显示的多个View Controller,同时,控制一个View Controller切换到另一个View Controller的方式。这里的UIPageViewController就是让用户可以在页面间导航的容器,每个页面都由对应的View Controller对象管理。下面的插图说明了Page View Controller和内容VC之间的关系。
在UIPageViewController开始工作之前,我们必须实现UIPageViewControllerDataSource协议。PageViewController的Data Source负责按照(PageViewController的)需要提供内容VC。我们通过实现Data Source协议告知PageViewController每个页面显示什么内容。
在这个例子中,我们使用ViewController类作为UIPageViewController的Data Source。因此需要声明在ViewController类中声明它实现了UIPageViewControllerDateSource协议。
ViewController类还负责向内容VC提高数据(图片和标题)。打开ViewController.h,修改@interface声明,添加一个新的属性来保存UIPageViewController,同样的,创建图片和标题的属性。
1 2 3 4 5 6 7 8 9 10 11 | #import <UIKit/UIKit.h> #import "PageContentViewController.h" @interface ViewController : UIViewController <UIPageViewControllerDataSource> - (IBAction)startWalkthrough:(id)sender; @property (strong, nonatomic) UIPageViewController *pageViewController; @property (strong, nonatomic) NSArray *pageTitles; @property (strong, nonatomic) NSArray *pageImages; @end |
在ViewController.m文件中,在viewDidLoad:方法中初始化标题和图片:
1 2 3 4 5 6 7 | - (void)viewDidLoad { [super viewDidLoad]; _pageTitles = @[@"Over 200 Tips and Tricks", @"Discover Hidden Features", @"Bookmark Favorite Tip", @"Free Regular Update"]; _pageImages = @[@"page1.png", @"page2.png", @"page3.png", @"page4.png"]; } |
注意:你能在这个链接下载这些图片并添加到你的Xcode项目中。
我们已经创建好了页面内容的数据模型。下一步,我们要至少实现UIPageViewControllerDataSource的以下两个方法:
- viewControllerAfterViewController - 提供当前View Controller的后一个View Controller。换言之,我们告诉app下一页显示什么内容。
- viewControllerBeforeViewController - 提供当前View Controller的前一个View Controller。换言之,我们告诉app上一页显示什么内容。
在ViewController.m文件的@end之前,添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #pragma mark - Page View Controller Data Source - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index = ((PageContentViewController*) viewController).pageIndex; if ((index == 0) || (index == NSNotFound)) { return nil; } index--; return [self viewControllerAtIndex:index]; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = ((PageContentViewController*) viewController).pageIndex; if (index == NSNotFound) { return nil; } index++; if (index == [self.pageTitles count]) { return nil; } return [self viewControllerAtIndex:index]; } |
上面的方法非常简单。首先,我们获取当前的页码,简单地增加/减少页码并返回要显示的View Controller。当然,我们需要做边缘检查,并在超出时返回nil。
正如你注意到的那样,我们还没有创建viewControllerAtIndex:方法。这是一个用来创建所需位置的内容VC的辅助方法。它接收一个index参数并创建对应的内容VC。
在ViewController.m文件中,添加这个辅助方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | - (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index { if (([self.pageTitles count] == 0) || (index >= [self.pageTitles count])) { return nil; } // Create a new view controller and pass suitable data. PageContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageContentViewController"]; pageContentViewController.imageFile = self.pageImages[index]; pageContentViewController.titleText = self.pageTitles[index]; pageContentViewController.pageIndex = index; return pageContentViewController; } |
还记得吗,我们在设计UI时为这些View Controller设置了ID。这个ID用于创建View Controller对象时的引用。为了实例化一个View Controller对象,你需要使用instantiateViewControllerWithIdentifier:方法,并传入一个ID。
1
| PageContentViewController *pageContentViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageContentViewController"];
|
为了显示页面指示器(Page Indicator),你需要告诉iOS Page View Controller要显示的页面的数量(也就是点的数量),以及初始选择那一页。在ViewController.m的底部添加以下两个方法:
1 2 3 4 5 6 7 8 9 10 | \- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController { return [self.pageTitles count]; } \- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController { return 0; } |
同样的,上面两个方法也非常简单。我们仅仅是告诉iOS我们一共需要显示多少页面,以及默认选择的第一页。
注意:你必须实现上面的方法才能显示页面指示器(Page Indicator)。而且,页面指示器只在滑动切换模式下起作用。
初始化UIPageViewController
最后一步就是创建并初始化UIPageViewController,最好的位置就是viewDidLoad方法。打开ViewController.m文件,修改viewDidLoad:方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - (void)viewDidLoad { [super viewDidLoad]; // Create the data model _pageTitles = @[@"Over 200 Tips and Tricks", @"Discover Hidden Features", @"Bookmark Favorite Tip", @"Free Regular Update"]; _pageImages = @[@"page1.png", @"page2.png", @"page3.png", @"page4.png"]; // Create page view controller self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"]; self.pageViewController.dataSource = self; PageContentViewController *startingViewController = [self viewControllerAtIndex:0]; NSArray *viewControllers = @[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; // Change the size of page view controller self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30); [self addChildViewController:_pageViewController]; [self.view addSubview:_pageViewController.view]; [self.pageViewController didMoveToParentViewController:self]; } |
让我们看一下这个方法做了什么。首先我们创建了PageViewController实例。随后我们制定了Data Source,在这个例子中就是这个类本身。然后我们创建了第一个内容VC并把它添加到一个Controller数组中,并且将它和要显示的ViewController关联。
最后,我们修改内容VC的大小并将内容VC的view添加到当前view中。
自定义Page Indicator
如果你现在编译并运行这个app,它会正常运行但是你可能会发现页面指示器并没有显示。事实上页面指示器已经显示了但是点的颜色和view的颜色一样,所以让我们来修改它的颜色吧。
在AppDelegate.m文件中,在didFinishLaunchingWithOptions:方法中添加下面几行代码:
1 2 3 4 | UIPageControl *pageControl = [UIPageControl appearance]; pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; pageControl.currentPageIndicatorTintColor = [UIColor blackColor]; pageControl.backgroundColor = [UIColor whiteColor]; |
编译并运行这个app
好了,启动这个应用然后看UIPageViewController运行得如何。你应该可以在iPhone模拟器中加载Page View Controller了。尝试在多个页面之间滑动一下。
返回首页
还有一件事没做。“Start again”按钮还没有实现功能。点击的时候,我们希望Page View Controller滑动到第一页。你可以使用UIPageViewController的setViewControllers:方法切换页面。为了回到第一页,修改ViewController.m的startWalkthrough:方法:
1 2 3 4 5 | - (IBAction)startWalkthrough:(id)sender { PageContentViewController *startingViewController = [self viewControllerAtIndex:0]; NSArray *viewControllers = @[startingViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; } |
再次运行app。点击“Start again”按钮会将你带回第一页。
总结
这篇教程中,我们介绍了UIPageViewController的基础知识并演示了如何使用Storyboard创建Controller。UIPageViewController是实现引导页的非常方便的类。同时,UIPageViewController的适用范围非常广阔,你可以用它来显示任意你想显示的信息,比如:多个网页。UIPageViewController还有丰富的配置项。这篇教程只涵盖了滑动样式,但是可别忘了你可以使用这个类简单地创建一个读书应用呢!只需要将滑动样式更改为翻页样式就可以了。所以别满足于这个小例子,尝试修改并了解UIPageViewController的其他选项吧。
如果需要完整参考,可以在这个链接下载Xcode项目。和往常一样,请将你的评论和想法告知我们。
Demo项目已本地到博主VPS,放心下载。
声明:本文翻译自AppCoda网站的文章:How To Create UIPageViewController Using Storyboard,如有异议,请联系博主。
原博客链接:https://blog.kyleduo.com/2014/10/21/trans_create_uipageviewcontroller_using_storyboard/