この記事は、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というように分類しています。
Traits
Size Classes等の、現在のデバイスの情報はUITraitCollection
というクラスで管理されています。
UITraitCollection
から、以下の情報を知ることができます。
- HotizontalのSize Class
- VerticalのSize Class
- iPhone/iPadのどちらのデバイスで表示しているか
- 画面の倍率
Unified Storyboards
これまで説明してきたAuto Layout、Size ClassesやTraitsを組み合わせることにより、1つのUniversal StoryboardでiPhone(4s〜6)/iPhone 6 Plus/iPadなどの異なるデバイスやportlait/landscapeに応じたレイアウトを指定する ことができるようになります。
具体的には、Size Classに応じたConstraintsを指定することにより、1つのStoryboardでも複数デバイスで破綻しないレイアウトを実現することができます。
StoryboardだけでiPhone/iPadのレイアウトを変更してみる
仕組みの話だけを追っていても何ができるのかわからないので、実際に手を動かしてみましょう。
iPhone(Portrait)とそれ以外の場合に、以下の通りレイアウトを変えるサンプルを作成してみます。
ソース一式はこちら。
Universal Device向けのプロジェクト作成
はじめに、何でも良いので適当なプロジェクトを作成します。
今回はiPhone/iPadの両方で使いたいので、"Device: "にはUniversal
を指定します。
どのSize Classでも画面の中央に表示されるUILabelを追加する
View Controllerの中心部に、UILabelを配置します。
Horizontal/VerticalのCenter In Controller
に、0を設定してConstraintsを追加します。
追加まで終わったら、動作確認してみます。
デバイス(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で、以下の通り操作します。
- デフォルトの行(何の説明もなく、Installedのチェックが付いている行)のチェックを外す
-
+
ボタンを押す - 表示された"Add Size Class Customization"で、
Regular Width -> Any Height
を選択する
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が有効になっているか確認することができます。
同じように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])