Swift Playgroundsで学ぶiOSプログラミング 第67回
プログラムコードだけでAuto Layoutを設定
画面サイズの変化に応じて最適なレイアウトを実現するプログラム
2017年12月13日 17時00分更新
今回からは、iOSアプリのユーザーインターフェースのレイアウトの基盤であるAuto Layoutを取り上げます。Auto LayoutはiOS 6から使えるようになった技術なので、すでにかなりの歴史があります。もちろんiOSだけでなく、macOSやその他のアップル製品のアプリでも標準的に使われているレイアウト手法です。
そもそもAuto Layoutは、画面サイズの変化に対応して最適なレイアウトを自動的に実現するために考えられたものです。当初、iPhoneの画面サイズは1種類しかなかったので、縦(ポートレート)と横(ランドスケープ)の2種類の画面サイズにだけ対応できればよかったのですが、iPhoneの画面サイズのバリエーションが増え続けるに従って何らかの自動レイアウト機能の導入が必要となりました。さらに最近では画面を分割して複数のアプリ画面を同時に表示することも可能になっているので、Auto Layoutの重要性もますます高まっています。
Auto Layout以前には、元来はMac用に開発されたAutosizingという技術があって、それでなんとかウィンドウ(画面)サイズ(比率)の変化に対応していました。iOS時代になってAuto Layoutにスイッチしたのは必然だったと言えるでしょう。
Auto Layoutは、Xcodeに含まれるユーザーインターフェースの作成ツール、Interface Builderを使って視覚的に設定するのが普通です。一方、プログラムのみによっても設定することも可能となっています。そうするとコードが煩雑になるという欠点もありますが、すべてをSwiftのソースコードで記述でき、見晴らしがよくなるというメリットもあります。
Swift Playgrounds上では、Interface Builderは使えませんが、すべてコードで記述することで、Auto Layoutも利用可能です。これまでこの連載では、ビューのフレームを直接設定することでレイアウトを実現してきました。プレイグラウンド上で動く比較的単純なプログラムでは、それでも構わないというより、そのほうが簡潔にレイアウトを実現できるのです。とはいえ、iOS、そのほかのアプリ開発で標準的に使われているAuto Layoutをまったく知らなくては比較もできません。そこで今回は、プレイグラウンドでも無理なく利用可能な範囲で、実際にAuto Layoutを使ってレイアウトしてみることにしました。
ビューの四辺を「拘束」することで、位置とサイズを同時に決める
まずAuto Layoutの基本的な機能を確認するために、ビューコントローラーを作成し、その中に1つのラベル(UILabel)を配置する例を見てみましょう。
ここまでのプログラムは、ラベルの背景色や表示テキストなどを初期設定しただけで、まだレイアウトは決めていません。この連載では、これまではviewWillLayaoutSubviewsメソッドを用意して、その中でラベルのframeをCGRectで設定していました。
今回はその代わりに、updateViewConstraintsメソッドの中でラベルにいくつかの「拘束(Constraint)」を設定しています。このConstraintを「制約」と訳している日本語のサイトがなぜか多いのですが、まったく不適切な訳語です。「制約」というのは、例えば「制約が多くて十分に活動できない」などといったように、なんらかの障害というニュアンスの強い言葉です。Auto LayoutのConstraintには、そのような否定的な意味はありません。Constraintが制約だと誤解していたら、Auto Layoutそのものを正しく理解することが難しくなるでしょう。
高校で習うような初歩の物理学をかじったことのある人なら、「拘束条件」という言葉を聞いたことがあるかと思います。実はその拘束条件に対応する英単語がConstraintなのです。Auto Layoutの設計者が、物理学の拘束条件をイメージしてConstraintという語を使ったことは間違いないでしょう。物理学の慣例に従えば、Constraintは拘束条件と訳すのが妥当です。ただし、この記事では本来の物理学のConstraintとの違いと、より簡潔な呼び名にすることを意識して、単に「拘束」と呼ぶことにします。
さて、この例ではラベルに4つの拘束を付加しています。これらは非常に単純で、ラベルを囲う長方形4辺を、対応する親のビューの4辺に一致する(equalTo)ように拘束しています。ただし、その際に定数(constant)を指定して間隔を30ポイントずつ開けています。
これによってラベルはビューコントローラーのビューの内側に、上下左右とも30ポイントの幅の余白を付けて配置されることになります。
実際に動かして確認してみましょう。
なお、実際に拘束を設定する前に、ラベルのtranslatesAutoresizingMaskIntoConstraintsという属性をfalseに設定しています。これは、Auto Layout以前のAutosizingによる自動レイアウト機能をAuto Layoutに自動的に移行する処理を無効にするためです。そうしないと、明示的に設定した拘束が有効になりません。この設定はAuto Layoutで配置するビュー(ここではラベル)ごとに必要です。また、updateViewConstraintsメソッドの中では、独自の拘束設定処理を実行した「後」に、親クラスの同名メソッドを呼び出す必要があることにも注意してください。
この連載の記事
- 第100回 SceneKitの物理現象シミュレーションとアニメーションをARKitに持ち込む
- 第99回 「物理学体」と「物理学場」を設定して物理現象をシミュレーション
- 第98回 SceneKitのノードに動きを加えるプログラム
- 第97回 いろいろな形のノードをシーンの中に配置する
- 第96回 SceneKitの基礎シーンビュー、シーン、ノードを理解する
- 第95回 現実世界の床にボールや自動車のモデルを配置する
- 第94回 ARKitを使って非現実世界との融合に備える
- 第93回 ARKitが使えるiPadを識別するプログラム
- 第92回 Swift Playgrounds 2.1での問題点をまとめて解消する
- 第91回 iPadの内蔵カメラで撮影した写真を認識するプログラム
- この連載の一覧へ