Managing the Page Navigation
-
currentPage
property -
numberOfPages
property -
hidesForSinglePage
property - 示范A= = == == = =
- 用UIPageViewController来实现,通过改变其所包含的viewcontroller,快速实现翻页效果,代码量最小,基本方法就是:
-
pageViewController viewControllerAfterViewController
pageViewController viewControllerBeforeViewController
-
// make a page view controller UIPageViewController* pvc = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; // give it an initial page Pep* page = [[Pep alloc] initWithPepBoy:[self.pep objectAtIndex:0] nib: nil bundle: nil]; //nib is nil as by default, it will go to load the nib with same name... [pvc setViewControllers:[NSArray arrayWithObject:page] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
-
- 从自动nib关联,动态调整view的内容。
-
- (void)viewDidLoad
{
[super viewDidLoad];
self.name.text = self.boy;
self.pic.image = [UIImage imageNamed:
[NSString stringWithFormat: @"%@.jpg", [self.boy lowercaseString]]];
}
==向前翻动和向后翻页 -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSString* boy = [(Pep*)viewController boy]; NSUInteger ix = [self.pep indexOfObject:boy]; //反向 的查找... ... ix++; if (ix >= [self.pep count]) return nil; return [[Pep alloc] initWithPepBoy:[self.pep objectAtIndex:ix] nib: nil bundle: nil]; //返回新对象 } //viewControllerBeforeViewController -(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSString* boy = [(Pep*)viewController boy]; NSUInteger ix = [self.pep indexOfObject:boy];//先获得内容 if (ix == 0) return nil; return [[Pep alloc] initWithPepBoy:[self.pep objectAtIndex:--ix] nib: nil bundle: nil];//后创建对象view controller }
示范B= = == == = =
用xcode 4.3 for iOS 5.0的默认template产生的翻页程序,由于采用了storyboard,似乎复杂了些!这个template的特别之处是没有机会让用户选择 是否要使用storeboard,
@property (strong, nonatomic) UIPageViewController *pageViewController;
self.pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil] autorelease]; self.pageViewController.delegate = self; flyDataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard]; NSArray *viewControllers = [NSArray arrayWithObject:startingViewController]; //set the viewcontroller as container... [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
基本来说,结构一样,先初始化自己,(这段代码是没有ARC启用的)然后初始化default viewcontroller,然后pageviewcontroller setViewcontrollers。这里的一个特别的地方是从storyboard获得sub viewcontroller。
@interface flyModelController : NSObject <UIPageViewControllerDataSource> - (flyDataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard;
//一般而言一个app一个storayboard,如此更具备通用性 - (NSUInteger)indexOfViewController:(flyDataViewController *)viewController;
在这个模板中,把//逆向计算viewController的index,用于定位下一个/上一个。。。 是两个辅助函数 @end
<UIPageViewControllerDelegate>和datasource协议分开在两个class中实现,上一个简洁的就直接在 appdelegate中全部搞定了
@interface AppDelegate : UIResponder <UIApplicationDelegate, UIPageViewControllerDataSource>
真正的datasource就是如下(和之前一样没什么。。。):
= = = =》storyboard中通过vc identifier来获取vc instance#pragma mark - Page View Controller Data Source - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { NSUInteger index = [self indexOfViewController:(flyDataViewController *)viewController];//method 1 if ((index == 0) || (index == NSNotFound)) { return nil; } index--; return [self viewControllerAtIndex:index storyboard:viewController.storyboard];//method 2 } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { NSUInteger index = [self indexOfViewController:(flyDataViewController *)viewController]; if (index == NSNotFound) { return nil; } index++; if (index == [self.pageData count]) { return nil; } return [self viewControllerAtIndex:index storyboard:viewController.storyboard]; }
// Create a new view controller and pass suitable data. flyDataViewController *dataViewController = [storyboard instantiateViewControllerWithIdentifier:@"flyDataViewController"]; dataViewController.dataObject = [self.pageData objectAtIndex:index];
datasource protocol。dataviewcontroller实现了view,以及如何把数据展现到view outlet了,算view;rootviewcontroller实现了
@interface flyRootViewController : UIViewController <UIPageViewControllerDelegate>,自然就是真正的controller。
那appdelegate只是作为一个entrance,custom 代码一点也没有,直接导向第一个rootviewcontroller,从之前的storyboard截图来看,两个viewcontroller之间没有segue,是通过代码方式使用的
//only one instance by getter inside class... //@synthesize modelController = _modelController; - (flyModelController *)modelController { // Return the model controller object, creating it if necessary. // In more complex implementations, the model controller may be passed to the view controller. if (!_modelController) { _modelController = [[flyModelController alloc] init]; } return _modelController; }
[self.view addSubview:self.pageViewController.view]; // Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages. CGRect pageViewRect = self.view.bounds; pageViewRect = CGRectInset(pageViewRect, 50.0, 40.0); self.pageViewController.view.frame = pageViewRect; [self.pageViewController didMoveToParentViewController:self]; //Called after the view controller is added or removed from a container view controller. // Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily. self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
这个代码还有些意思的,通过subview利用了原windowview的边框,通过didmovetoparentviewcontroller可以实现与presented viewcontroller交互,通过gesture的转移,方便了翻页因为我们留了边界,这么做可以帮助翻页手势识别从边上开始。
delegate的方法基本是 optional的,实现了一个,就是在landscape时候,书本是双页显示内容的,那么要计算view的位置:
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { if (UIInterfaceOrientationIsPortrait(orientation)) { // In portrait orientation: Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here. UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSArray *viewControllers = [NSArray arrayWithObject:currentViewController]; [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; self.pageViewController.doubleSided = NO; return UIPageViewControllerSpineLocationMin; } // In landscape orientation: Set set the spine location to "mid" and the page view controller's view controllers array to contain two view controllers. If the current page is even, set it to contain the current and next view controllers; if it is odd, set the array to contain the previous and current view controllers. flyDataViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0]; NSArray *viewControllers = nil; NSUInteger indexOfCurrentViewController = [self.modelController indexOfViewController:currentViewController]; if (indexOfCurrentViewController == 0 || indexOfCurrentViewController % 2 == 0) { UIViewController *nextViewController = [self.modelController pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController]; viewControllers = [NSArray arrayWithObjects:currentViewController, nextViewController, nil]; } else { UIViewController *previousViewController = [self.modelController pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController]; viewControllers = [NSArray arrayWithObjects:previousViewController, currentViewController, nil]; } [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL]; return UIPageViewControllerSpineLocationMid; }