hyoromoのブログ

最近はVRSNS向けに作ったものについて書いています

UIPageViewControllerの使い方 -Tips-

以前にブログで書いた「UIPageViewControllerの使い方 -基礎-」の続きとなります。前は基礎的な使い方を説明しましたが、今回はXcodeテンプレートに無い機能や豆知識について触れていくTips編となります。以前のプロジェクトを度々参照するので、まずは前回のブログ内容からお読みください。

ページ移動を横スクロールのアニメーションにする

デフォルトは紙をめくるようなアニメーションですが、横へスクロールしてページ単位で切り替えるアニメーションにする事がiOS6.0以上なら可能です。
なお、UIScrollViewで内部Viewを横に連ねて横移動させた時とアニメーションが同じです。あえてUIPageViewControllerで行う理由はページ移動をコントロールしやすい点、設定切り替え等で紙めくりとの共存可能な点です。

// インスタンス生成
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

お分かり頂けたでしょうか?initWithTransitionStyleに指定する引数が以下の2種類存在し、それを返ることでアニメーション方法が切り替わるのです。

定数名 アニメーション方法
UIPageViewControllerTransitionStylePageCurl 紙めくる
UIPageViewControllerTransitionStyleScroll 横スクロール

ページめくり方法を右開きにする

デフォルトは左開き(右から左に向かってページを移動)ですが、右開き(左から右に向かってページを移動)するよう変更する事が可能です。国内向けの電子書籍ならば右開きにする必要があり、必須対応となるでしょう。
対応箇所は2箇所あり、以前のブログ内容を参照しながら内容を記載します。

RootViewController.m
// ページめくりに関するオプション設定
NSMutableDictionary *opt = [NSMutableDictionary dictionary];
[opt setObject:[NSString stringWithFormat:@"%d", UIPageViewControllerSpineLocationMax] forKey:UIPageViewControllerOptionSpineLocationKey]; // デフォルト値を設定したい場合は UIPageViewControllerSpineLocationMin になります

// インスタンス生成。optionsに先ほど準備したoptを設定
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:opt];
ModelController.m
// UIPageViewController上で右スワイプした時に呼ばれるメソッド
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    // ページの整合性をチェック
    // 左開きか右開きかでここの処理は変わり、以下のコードは左開きの場合の処理です
    NSInteger page = [self indexOfViewController:(MangaDataViewController *)viewController];
    if (page == NSNotFound) {
        return nil;
    }
    if (page == [self.pageData count] - 1) {
        return nil;
    }
    page++;
    
    // 前述したようにページのインスタンス生成を行う
    return [self viewControllerAtIndex:page storyboard:viewController.storyboard];
}

// UIPageViewController上で左スワイプした時に呼ばれるメソッド
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSInteger page = [self indexOfViewController:(MangaDataViewController *)viewController];
    if (page == NSNotFound) {
        return nil;
    }
    if (page == 0) {
        return nil;
    }
    page--;
    
    return [self viewControllerAtIndex:page storyboard:viewController.storyboard];
}

**ページ周囲に余白を入れる
UIPageViewController内部で縁に余白を持たせることが可能です。<br>インスタンス生成時に、先ほどのページめくりでも設定したオプションを使って余白を指定します。
>|objc|
// ページめくりに関するオプション設定
NSMutableDictionary *opt = [NSMutableDictionary dictionary];
[opt setObject:[NSNumber numberWithInt:5] forKey:UIPageViewControllerOptionInterPageSpacingKey]; // 幅5ほど余白をいれる

// インスタンス生成。optionsに先ほど準備したoptを設定
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:opt];

ページをジャンプ移動

ページをまたいで移動可能です(例:1Pから20Pへジャンプ移動)。コード中のmodelController変数はUIPageViewControllerの初期化を行った時のModelControllerインスタンス変数です。

// 20Pへジャンプ移動
RootViewController *viewController = [modelController viewControllerAtIndex:20 storyboard:self.storyboard];
NSArray *viewControllers = @[viewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

現在表示中のページ番号を取得

modelController変数は先ほどと同様。なお、ModelController.mコード上のindexOfViewControllerメソッドを前回ブログ内容と同様にしている必要があります。

int pageNo = [modelController indexOfViewController:[self.pageViewController.viewControllers objectAtIndex:0]];

まとめ

だいたいこんなところだと思います。
あとは画像の拡縮が必要だったり、タップ/ダブルタップでイベント発生させたい場合は自力で頑張ってみてください。UIPageViewController関係なく他で行なっている事と同様に行えば実装可能な内容です。