41
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

Organization

これからの「iPhoneX」の話をしよう。 - UITableView、UICollectionView編

はじめに

この投稿はAbemaTV Advent Calendar 2017 14日目の記事です!

今回は、現在AbemaTV iOSチームのメンバーの一人であるcokaholicこと、辰己が担当します。

以前、【随時更新】iPhoneX完全対応マニュアル という投稿を書いたのですが、その中では触れられていない、これから新規でiOSアプリを開発する方のための具体的なiPhoneX対応AutoLayoutの使い方をご紹介しようと思います。
今回は普段よく使うUITableView編UICollectionView編です!

UITableView編

まずは、UITableViewのStoryboard上におけるAutoLayoutの使い方について話そうと思います。

Xcode9からはStoryboard内でUIViewControllerを作成すると、デフォルトで Use Safe Area Layout Guides にチェックが入っており、初めから SafeArea (UILayoutGuide) が追加されています。

UseSafeAreaLayoutGuides

そして、適当に中身を見繕ったUITableViewに、以下のように SafeAreaの各Edgeに対して制約を追加した場合SuperView(今回はUIViewControllerのview)の各Edgeに対して制約を追加した場合 だと、どのような見た目になるでしょうか?

SafeAreaの各Edgeに対して制約を追加 SuperViewの各Edgeに対して制約を追加
SafeArea SuperView

ちなみに、 SuperViewへの制約の追加方法は、SafeAreaに制約を追加した後、追加した制約のFirstItemをSafeAreaからSuperViewに変更すれば適用することができます。
スクリーンショット 2017-12-14 3.46.38.png

SafeAreaの各Edgeに対して制約を追加した場合

Portrait Landscape
tate yoko

SafeAreaに対して制約を追加した場合、UITableViewのフレームサイズはSafeArea内に収まります。
そのため、Portraitの際には上:44pt、下:34pt、Landscapeの際は左右:44pt, 下:21pt がフレーム外となり、切れて表示されます。
しかし、これでは見た目が悪すぎますし、iPhoneXの凹みを活かしきれていないレイアウトになってしまっています。

SuperViewの各Edgeに対して制約を追加した場合

Portrait (Top) Landscape (Top)
tate yoko
Portrait (Bottom) Landscape (Bottom)
tate yoko

続いて、SuperViewであるUIViewControllerのviewの各Edgeに対して制約を追加した場合、UITableViewのフレームサイズは画面全体に広がります。
ですが、各画面に注目すると、 上部と下部にセーフエリア分のinset が設けられていることがわかります。
これは、UITableViewの親クラスであるUIScrollViewの contentInsetAdjustmentBehavior プロパティによるものです。
デフォルトのAutomaticを指定しておけば、Viewの各Edgeに制約を追加した際にそのViewのsafeAreaInsetsの値に応じて自動で上下にセーフエリア分のinsetを追加してくれます。
Storyboard上とコード上で指定する場合はそれぞれ以下のようになります。

Storyboard上で指定する場合

UseSafeAreaLayoutGuides

コード上で指定する場合

// iOS11からしか指定できないので、iOS10以下もサポートする場合は分岐を追加
if #available(iOS 11, *) {
    tableView.contentInsetAdjustmentBehavior = .automatic
}

さらに、Landscapeの際の画面に注目すると、 UITableViewのセルの左右にセーフエリア分のinset が設けられていることがわかります。
これは、UITableViewの insetsContentViewsToSafeArea プロパティによるものです。
insetsContentViewsToSafeAreaを有効にしておけば、Viewの各Edgeに制約を追加した際にそのViewのsafeAreaInsetsの値に応じて自動でセルの左右にセーフエリア分のinsetを追加してくれます。
Storyboard上とコード上で指定する場合はそれぞれ以下のようになります。

Storyboard上で指定する場合

UseSafeAreaLayoutGuides

コード上で指定する場合

// iOS11からしか指定できないので、iOS10以下もサポートする場合は分岐を追加
if #available(iOS 11, *) {
    tableView.insetsContentViewsToSafeArea = true
}

UICollectionView編

続いて、UICollectionViewのStoryboard上におけるAutoLayoutの使い方について話そうと思います。

適当に中身を見繕ったUICollectionViewに、先ほどと同じく以下のように SafeAreaの各Edgeに対して制約を追加した場合SuperView(今回はUIViewControllerのview)の各Edgeに対して制約を追加した場合 だと、どのような見た目になるでしょうか?

SafeAreaの各Edgeに対して制約を追加 SuperViewの各Edgeに対して制約を追加
SafeArea SuperView

SafeAreaの各Edgeに対して制約を追加した場合

Portrait Landscape
tate yoko

SafeAreaに対して制約を追加した場合、UICollectionViewのフレームサイズはSafeArea内に収まります。
そのため、Portraitの際には上:44pt、下:34pt、Landscapeの際は左右:44pt, 下:21pt がフレーム外となり、切れて表示されます。
またしてもiPhoneXの凹みを活かしきれていないレイアウトになってしまっています。

SuperViewの各Edgeに対して制約を追加した場合

Portrait (Top) Landscape (Top)
tate yoko
Portrait (Bottom) Landscape (Bottom)
tate yoko

続いて、SuperViewであるUIViewControllerのviewの各Edgeに対して制約を追加した場合、UICollectionViewのフレームサイズは画面全体に広がります。
ですが、各画面に注目すると、 上部と下部にセーフエリア分のinset が設けられていることがわかります。
これも先ほどと同じく、UICollectionViewの親クラスであるUIScrollViewの contentInsetAdjustmentBehavior プロパティによるものです。

しかし、今回はUITableViewの場合と比べて、Landscapeの表示に大きな違いがあります。
そうです、Landscape時のcontentViewに対する左右のセーフエリアマージン が無いのです。
これでは左右のマージン分はみ出してしまう...美しくない...

でもご安心を。ちゃんと対応する方法は用意されています!

解決方法

具体的な解決方法としましては、UICollectionViewFlowLayoutの sectionInsetReference プロパティを変更することで解決します。
まず、Storyboard上では指定できないため、以下のようにIBOutletでUICollectionViewFlowLayoutを接続します。

Bind

次に、接続したflowLayoutを以下のように書き換えましょう。
ここのdidSet内にて、sectionInsetReference.fromSafeArea を指定することで完了です。

@IBOutlet weak var flowLayout: UICollectionViewFlowLayout! {
    didSet {
        // iOS11からしか指定できないので、iOS10以下もサポートする場合は分岐を追加
        if #available(iOS 11, *) {
            flowLayout.sectionInsetReference = .fromSafeArea
        }
    }
}

実行してみると、以下のように無事にcontentViewの左右にセーフエリアマージンができていることがわかります。

スクリーンショット 2017-12-14 14.53.12.png

まとめ

今回はここまでです!
UITableViewもUICollectionViewも基本はSuperViewの各Edgeに対して制約を貼ることで、iPhoneXでも違和感の無い、凹みを活かしたレイアウトが可能です。

最後に、私はiPhoneX対応をがっつり担当したのですが、普段はiPhone8を使用していますw
CPUも高速になり、反応速度も大幅に向上したTouchIDはすごく便利ですね(ニッコリ)

以上です!
最後まで読んでいただき、ありがとうございました!

参考リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
41
Help us understand the problem. What are the problem?