このページの本文へ

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)を配置する例を見てみましょう。

最も単純なAuto Layoutを試すために、ビューコントローラーとそのビューの上に配置するラベルを1つ用意しました

 ここまでのプログラムは、ラベルの背景色や表示テキストなどを初期設定しただけで、まだレイアウトは決めていません。この連載では、これまではviewWillLayaoutSubviewsメソッドを用意して、その中でラベルのframeをCGRectで設定していました。

 今回はその代わりに、updateViewConstraintsメソッドの中でラベルにいくつかの「拘束(Constraint)」を設定しています。このConstraintを「制約」と訳している日本語のサイトがなぜか多いのですが、まったく不適切な訳語です。「制約」というのは、例えば「制約が多くて十分に活動できない」などといったように、なんらかの障害というニュアンスの強い言葉です。Auto LayoutのConstraintには、そのような否定的な意味はありません。Constraintが制約だと誤解していたら、Auto Layoutそのものを正しく理解することが難しくなるでしょう。

 高校で習うような初歩の物理学をかじったことのある人なら、「拘束条件」という言葉を聞いたことがあるかと思います。実はその拘束条件に対応する英単語がConstraintなのです。Auto Layoutの設計者が、物理学の拘束条件をイメージしてConstraintという語を使ったことは間違いないでしょう。物理学の慣例に従えば、Constraintは拘束条件と訳すのが妥当です。ただし、この記事では本来の物理学のConstraintとの違いと、より簡潔な呼び名にすることを意識して、単に「拘束」と呼ぶことにします。

 さて、この例ではラベルに4つの拘束を付加しています。これらは非常に単純で、ラベルを囲う長方形4辺を、対応する親のビューの4辺に一致する(equalTo)ように拘束しています。ただし、その際に定数(constant)を指定して間隔を30ポイントずつ開けています。

これまでは、viewWillLayoutSubviewsメソッドの中でビューのフレームを直接設定していましたが、今回はupdateViewConstraintsメソッドの中で、Auto Layoutのための拘束を設定しています

 これによってラベルはビューコントローラーのビューの内側に、上下左右とも30ポイントの幅の余白を付けて配置されることになります。

この例では、ビューの中に配置したラベルの4辺を、それぞれ対応するビューの辺に拘束することで、ビューのサイズの変化に自動的に対応させます。その際、各拘束には少し間隔を指定して余白を付けています

 実際に動かして確認してみましょう。

プログラムを実行すると、ビューコントローラーのビューの4辺から少し間隔を空けてラベルの4辺がレイアウトされた画面が表示されます

 なお、実際に拘束を設定する前に、ラベルのtranslatesAutoresizingMaskIntoConstraintsという属性をfalseに設定しています。これは、Auto Layout以前のAutosizingによる自動レイアウト機能をAuto Layoutに自動的に移行する処理を無効にするためです。そうしないと、明示的に設定した拘束が有効になりません。この設定はAuto Layoutで配置するビュー(ここではラベル)ごとに必要です。また、updateViewConstraintsメソッドの中では、独自の拘束設定処理を実行した「後」に、親クラスの同名メソッドを呼び出す必要があることにも注意してください。

この連載の記事

週間ランキングTOP5

ASCII倶楽部会員によく見られてる記事はコレだ!

ASCII倶楽部の新着記事

会員専用動画の紹介も!