Help us understand the problem. What is going on with this article?

Adaptive UI Designについてのまとめ(Unified Storyboards, Size Classes, etc...)

More than 5 years have passed since last update.

この記事は、WWDC2014で発表されたBuilding Adaptive Apps with UIKitを元に、以下の項目についてまとめています。

  • Adaptive UIについてのざっくりとしたまとめ
    • Size Class
    • Traits
    • Unified Storyboards
  • Interface Builderを使った簡単なサンプル
    • Size Classごとに画面のレイアウトを変えてみる(Size Classに応じて適用されるConstraintsを変える)

以下の項目については、この記事では触れません。別な記事で説明します。
* Appearance Proxy
* Split View Controller

前提知識

Adaptive UI Design

解像度や画面サイズの異なるデバイスに対応するため、iOS8以降はAdaptive User Interfaceという考え方が取り入れられました。

ざっくりといえば、iOS6以降で導入されたAuto Layoutや、iOS8以降で導入されたSize ClassesやTraitsなどを組み合わせることにより、複数のデバイスに対応したレイアウトを作成するということを意図しているようです。

Auto Layout

詳しい資料はたくさんあるので、ここでは割愛します………

Size Classes

異なる解像度のデバイスの画面サイズは、Size Classesにて管理されます。
デバイスの画面サイズや解像度、デバイスの向きに応じて、Compact/Regular、Horizontal/Verticalというように分類しています。

sizeClasses.jpg

Traits

Size Classes等の、現在のデバイスの情報はUITraitCollectionというクラスで管理されています。
UITraitCollectionから、以下の情報を知ることができます。
* HotizontalのSize Class
* VerticalのSize Class
* iPhone/iPadのどちらのデバイスで表示しているか
* 画面の倍率

Unified Storyboards

これまで説明してきたAuto LayoutSize ClassesTraitsを組み合わせることにより、1つのUniversal StoryboardでiPhone(4s〜6)/iPhone 6 Plus/iPadなどの異なるデバイスやportlait/landscapeに応じたレイアウトを指定する ことができるようになります。
具体的には、Size Classに応じたConstraintsを指定することにより、1つのStoryboardでも複数デバイスで破綻しないレイアウトを実現することができます。

StoryboardだけでiPhone/iPadのレイアウトを変更してみる

仕組みの話だけを追っていても何ができるのかわからないので、実際に手を動かしてみましょう。

iPhone(Portrait)とそれ以外の場合に、以下の通りレイアウトを変えるサンプルを作成してみます。
design.jpg

ソース一式はこちら

Universal Device向けのプロジェクト作成

はじめに、何でも良いので適当なプロジェクトを作成します。
今回はiPhone/iPadの両方で使いたいので、"Device: "にはUniversalを指定します。

project.png

どのSize Classでも画面の中央に表示されるUILabelを追加する

View Controllerの中心部に、UILabelを配置します。

Horizontal/VerticalのCenter In Controllerに、0を設定してConstraintsを追加します。

horizontal_vertical_center.png

追加まで終わったら、動作確認してみます。
デバイス(iPhone/iPad)やPortrait/Landscapeを切り替えても、画面の中心にLabelが表示されます。

横一列に並ぶUIButtonを追加する

次に、UIButtonをLabelの下で横一列に並ぶよう配置します。

配置後、適当にConstraintsを設定してください。

Constraintsに、iPhone(Landscape)、iPadでのみ有効になる設定を追加する

次に、iPhone(Landscape)・iPadで表示した時(Size ClassがWidth: Regular Height: Any)のみ横一列に並ぶよう、Constraintsの設定を変更します。
追加したConstraintsを選択した状態で、Size Inspectorの中にあるSize Classで、以下の通り操作します。

  1. デフォルトの行(何の説明もなく、Installedのチェックが付いている行)のチェックを外す
  2. ボタンを押す
  3. 表示された"Add Size Class Customization"で、Regular Width -> Any Heightを選択する

addConstraint_1.jpg
addConstraint_2.jpg

UIButton配置時に追加したConstraints全てに対し、同じように操作してください。

この状態で動作確認すると、iPhone(Landscape)とiPadの場合のみ、追加したボタンが横一列に並んで表示されます。

iPhone(Landscape)のSize Classが指定された時に、UIButtonが縦に並ぶようConstraintsを追加する

次に、iPhone(Portrait)の時にはUIButtonが画面の中心で縦一列に並ぶようConstraintsを追加します。

左のUIButtonを選択し、Horizontal Center In Controller: 0のConstraintsを追加してください。
追加後、先ほどと同じように、Size Inspectorを使ってCompact Width -> Any Heightの時に有効となる条件を追加します。
もうひとつのUIButtonについても、同じようにHorizontal Center In Controller: 0で、Compact Width -> Any HeightのSize Classで有効になるConstraintsを追加してください。
また、x方向のConstraintsも忘れずに追加してください。

この状態で動作確認すると、iPhone(Portrait)で、UIButtonが縦一列に並んで表示されます。

Size Class Controlでレイアウトを確認する

ここまで操作した内容は、Interface BuilderのSize Class Controlから確認することもできます。

試しに、iPhone(Portrait)の状態でどのようにConstraintが適用されるか確認してみましょう。
InterfaceBuilderでView Controllerを選択し、画面下部にあるSize Class Control(w Any|h Anyなどで表示されている)で、Compact Width |Any Heightとなるよう領域を選択します。
選択されると、Size Classが"Compact width/Any Height"の状態でどのようなConstraintsが有効になっているか確認することができます。
sizeClassControl_1.jpg
sizeClassControl_2.jpg
sizeClassControl_3.jpg

同じようにSize Classを変更することで、iPhone(Landscape)などの状態も見ることができます。

気になった点

Auto Layoutの知識が前提となる

基本的に、Constraintsの使い方が肝になりますのでAuto Layoutの知識が必要になります。
あらかじめ資料を読むなど、事前知識がある方が理解しやすいです。

Constraintsの管理が大変そう

同じ要素に対して複数のConstraintsを設定することになるので、どの部品に対するものなのか、どの条件のときに有効となるのか、非常にわかりづらくなります。
いつ、何に対して有効となるConstraintsなのか、はっきりとわかる名前をつけるなどの方法でカバーする方が良いと思います。

iPhone デバイス間の解像度・画面サイズ差の吸収方法

Size ClassやTraitsを使えば、iPhone/iPadのデバイス差は検知できます。
ただ、UserInterfaceIdeomはiPhone/iPadの2種類、UIUserInterfaceSizeClassはUnspecified/Compact/Regularの3種類しかありません。
これらの情報からはiPhoneのデバイス差(4s/5系/6/6Plus)を検知できないので、別な方法で検知する必要があります。

iOS7 後方互換性の確保

Appleのドキュメントに記載されているとおり、以下のような条件が満たされればiOS7でもSize Classesを指定したStoryboardを使うことができます。

  • アプリがXcode6以降でビルドされた
  • deployment targetがiOS8以前
  • storyboardやxibでSize Classが指定されている
  • Size ClassのHeightがCompactではない

ただし、Compact heightのものは適用されないと記載されていますので、iPhone(Portrait)の場合には適用されません。
また、iOS7ではnibにSize Classが適用されないという不具合が存在しているようです。

いずれにせよ、iOS7で適用するときは

  • iPhoneではPortraitの画面を前提に適用する
  • nibはSize Classに依存しないよう実装する

などの注意を払って実装するほうが良さそうです。

参考にしたURL

WWDC 2014

What's New in Cocoa Touch
Building Adaptive Apps with UIKit
What's New in Interface Builder

Apple Developer Library

What's New In iOS: iOS8
iOS Human Interface Guidelines Adaptivity and Layout
Deploying an App With Size Classes on Earlier iOS Versions
AdaptivePhotos: An Adaptive Application

Others

iMore: Adaptive UI in iOS 8: Explained
Beginning Adaptive Layout Tutorial
Nerdely: Overcoming the iPad Tax With iOS 8 and Adaptive UI
Xamarin: Introduction to Unified Storyboards
stackoverflow: Design app that supports both iOS8 and iOS7
stackoverflow: Xcode6 Universal Storyboards and view sizing
stackoverflow: Xcode 6 – Unified storyboard & Size Classes
stackoverflow: How can Xcode 6 adaptive UIs be backwards-compatible with iOS 7 and iOS 6?
stackoverflow: Example for iPhone portrait landscape adaptive UI which is backwards-compatible with iOS 7])

jrits
信頼と魅力のある先進のITをもとに、お客様のワークスタイル・イノベーションの実現を目指します。
http://www.jrits.co.jp/
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