UIPageViewControllerやContainer View上のUITableViewやUIWebViewでバーのtranslucentに対応する

  • 8
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

もう懐かしい話となってしまいますが、UITableViewControllerやUICollectionViewController、WebViewを全画面で配置する際には、上端と下端をLayout Guide ではなく UIViewControllerのrootの view全体に 対するConstraintsを追加する必要があります。

これによって、UITableView、UICollectionView、UIScrollView、UIWebViewがUINavigationBar、UITabBar、UIToolBarの下に潜り込み(automaticallyAdjustsScrollViewInsetsがオンの場合)、透過されたBarの下にも表示されるようになります。

http://qiita.com/yimajo/items/254c7cebab7864678246

ただ、automaticallyAdjustsScrollViewInsetsは Child View Controller に対しては働かないという弱点があります。Child View Controllerとは、View Controllerの中にView Controllerを埋め込んでいる状態です。例えば、 UIPageViewContorller やInterface Builder上で指定できる Container View を使った場合はこの状態になります。

そこで、Layout Guideのある一番親のViewControllerまでさかのぼって、Layout Guideの幅をゲットし、それをUIScrollViewにセットするスニペットを使っています。

+ (void)setupInsetForScrollView:(UIScrollView *)scrollView onChildViewController:(UIViewController *)viewController
{
    if (!viewController.automaticallyAdjustsScrollViewInsets) {
        return;
    }
    UIViewController *currentViewController = viewController;
    UIViewController *rootParentViewController;
    while (currentViewController.parentViewController) {
        currentViewController = currentViewController.parentViewController;
        if ([currentViewController isKindOfClass:[UITabBarController class]] ||
            [currentViewController isKindOfClass:[UINavigationController class]] ||
            [currentViewController isKindOfClass:[UIPageViewController class]]) {
            continue;
        }
        rootParentViewController = currentViewController;
    }
    if (!rootParentViewController) {
        return;
    }

    // http://stackoverflow.com/a/21541533/1474113
    CGFloat topLength = rootParentViewController.edgesForExtendedLayout & UIRectEdgeTop ?
        rootParentViewController.topLayoutGuide.length : 0;
    CGFloat bottomLength = rootParentViewController.edgesForExtendedLayout & UIRectEdgeBottom ?
        rootParentViewController.bottomLayoutGuide.length : 0;
    UIEdgeInsets insets = UIEdgeInsetsMake(topLength, 0.0, bottomLength, 0.0);
    scrollView.contentInset = scrollView.scrollIndicatorInsets = insets;
}

これをChild View Controllerからこんな感じでviewWillLayoutSubviewsの時に呼び出せば自動調整されます・・!

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [YPLayoutGuideHelper setupInsetForScrollView:self.collectionView onChildViewController:self];
}

https://gist.github.com/ypresto/2f448ff5ec3a9f8ba637

※UIWebViewの場合はwebView.scrollViewを渡してください!