iOSでの読みやすい幅

モバイル基盤グループのヴァンサン(@vincentisambart)です。

iOSの設定画面の右側は一定の幅を超えないように作られています。

  • iPadでは: iPadでの設定画面

  • 新iPad Pro 12.9"では: iPad Pro 12.9インチでの設定画面

iPadでTwitterのタイムラインのセルの中身も一定の幅を超えません。

iPad Twitter

このように、自分のアプリで広い画面でもコンテンツが広がりすぎないようにするためにはどうすればよいのでしょうか。AutoLayoutでいくつかの制約を使ってできるのですが、もっと簡単な方法はないのでしょうか。

iOS 9以上では、端末の種類を気にせず、複雑なAutoLayout制約を使わず、殆どのビューですぐ使える仕組みがあります。Appleのドキュメントで「readable content」や「readable width」と呼ばれているものです。以下日本語で「読みやすい幅」と呼ぶことにします。

注意点:下記の説明はAutoLayoutを使う前提で書かれています。AutoLayoutを使わない場合、親ビューのreadableContentGuidelayoutFrameで読みやすい幅の明確な数字が取れるので、それを元にレイアウトを計算することになるのではないでしょうか。

(Twitterは読みやすい幅機能が使える前からこの表示でしたので、実際独自で同じことを実装しているようです。)

読みやすい幅とは

文章の表示領域の幅が広がりすぎると、少し読みづらく感じてしまいませんか。iOS 9以上では、readableContentGuideを使って幅が広がりすぎないようにできます。ビューのレイアウトの制約を定義する時、親ビューのleadingAnchor/trailingAnchor/leftAnchor/rightAnchorlayoutMarginsGuideの代わりにreadableContentGuideを使います。(因みに読みやすい幅のためのガイドなので、readableContentGuideの垂直方向のアンカーtopAnchorbottomAnchorcenterYAnchorheightAnchorが実質layoutMarginsGuideのと同じです)

縦向きのiPhoneにしか表示されないコンテンツは読みやすい幅を使うメリットがあまりないのですが、iPadや横向きのiPhoneでも表示されるコンテンツは画面の全幅に渡ると少し読みづらくなるので読みやすい幅を適切に使えば良いではないでしょうか。

因みに「読みやすい」といっても、テキストの幅を合わせるだけでなく、セルに入っている画像やボタンの配置も読みやすい幅に合わせたほうが自然だと思います。

「読みやすい幅」は具体的にどういう幅なのでしょうか。全画面のroot view controllerのビューに子ビューを貼って、その子ビューの制約を親ビューのreadableContentGuideに合わせて、子ビューの幅を測ってみました。

iPadでの表示: f:id:vincentisambart:20181206092236p:plain

端末 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
iPhone Xs Max
iPhone Xr
iPhone 8 Plus
414 pt 374 pt 40 pt 20 pt
iPhone Xs Max
iPhone Xr
896 pt 672 pt 224 pt 112 pt
iPhone 8 Plus 736 pt 696 pt 40 pt 20 pt
iPhone Xs
iPhone 8
375 pt 343 pt 32 pt 16 pt
iPhone 8 667 pt 627 pt 40 pt 20 pt
iPhone Xs 812 pt 772 pt 40 pt 20 pt
iPhone SE 320 pt 288 pt 32 pt 16 pt
iPhone SE 568 pt 528 pt 40 pt 20 pt
iPad 768 pt 672 pt 96 pt 48 pt
iPad 1024 pt 672 pt 352 pt 176 pt
iPad Pro 11" 834 pt 672 pt 162 pt 81 pt
iPad Pro 11" 1194 pt 672 pt 522 pt 261 pt

上記のサイズは画面の全幅のを使う場合の数字ですが、readableContentGuideが必ず自分のビューのlayoutMarginsGuideに収まるように設計されているので、上記の幅が最大値です。親ビューのマージンがもっと大きかったり、親ビューがもっと小さかったりすると、読みやすい幅が小さくなります。

また、注意すべき点として、readableContentGuidelayoutMarginsGuideの水平方向で中央になるように設計されているので、左右のマージンが違っていれば、readableContentGuideがビューの中央になりません。ただ様々な設定によって(マージンが例えばsafe areaを含むように)マージンが変わるので、指定した左右のマージンが違ってもreadableContentGuideがビューの中央になることもあります。

表の数字をまとめてみると、iPadでは、画面サイズや向きが何であろうと、幅が最大672 ptになるように計算されているようです(上記の表に載っていないiPad Pro 10.5"もiPad Pro 12.9"もそうです)。横向きのiPhone XsやiPhone 8 Plusでは、読みやすい幅がiPadより大きくなるのか少し気になりますが。

縦向きのiPhoneではreadableContentGuideを使うと左右の余白が最低でも16 ptになるように見えます(因みにiOSで殆どのビューの標準のマージンが8 ptです)。ただし、色んなケースを試してみると、親ビューが全画面でない場合、左右の余白が12 ptになったりしますし、layoutMarginsdirectionalLayoutMarginsで(またはInterface Builderで)親ビューのマージンを小さくすると、読みやすい幅の左右の余白がもっと小さくなることがあります。絶対なのはマージンに収まるように設計されているところだけのようですね。

上記の数字にはsafe areaが含まれていません。readableContentGuideをそのまま使うとsafe area外になる可能性があります。本当に画面全体でreadableContentGuideを使う場合、そのreadableContentGuideを持っているビューのinsetsLayoutMarginsFromSafeAreatrueにすれば良いかもしれません。insetsLayoutMarginsFromSafeAreatrueにすると、マージンにsafe areaが含まれるようになり、readableContentGuideがマージン内になるように設計されているので、readableContentGuideもsafe area内になります。因みに、safe area関連の機能は全部iOS 11以上でしか使えません。

Interface Builder

コードでは、readableContentGuideを使って制約を定義すれば良いのですが、ビューをInterface Builderで配置する場合、どうすれば良いのでしょうか。

やるべきことが2つあります:

  • 読みやすい幅に合わせたいビューの親ビューのレイアウトの設定に「Follow Readable Width」にチェックを入れます。

    f:id:vincentisambart:20181206090752p:plain:w295

  • 読みやすい幅に合わせたいビューの配置に使われるsuperviewに対する左右の制約がマージンに対する制約である必要があります。
    • 制約の詳細にある「First/Second Item」が「Superview.Leading」や「Superview.Trailing」ではなく、「Superview.Leading Margin」や「Superview.Trailing Margin」である必要があります。変えるには、その「First/Second Item」をクリックして、出てくるメニューに「Relative to margin」を選びましょう。

      f:id:vincentisambart:20181206091213p:plain:w295

    • 「First/Second Item」が「Safe Area」の場合、それをまず「Superview」に変えてから、「Relative to margin」を選びましょう。

      f:id:vincentisambart:20181206091038p:plain:w295

ビューが必ずsafe area内に配置されるようにしたかったら、親ビューのレイアウト設定に「Safe Area Relative Margins」にチェックを入れてください。コード上ではinsetsLayoutMarginsFromSafeAreaと同じです。

Dynamic Type

読みやすい幅は便利そうではありますが、使う前に注意すべき点が1つあります:Dynamic Typeです。

Dynamic Typeというのはユーザーが使われるフォントのサイズを変えられる機能です。iOS全体の設定に一般→アクセシビリティ→さらに大きな文字(英語だとSettings→General→Accessibility→Larger Text)で変えられます。対応しているアプリではフォントサイズがその設定に合わせられます。もっと詳しくはDynamic Typeのまとめ記事をご覧ください。

readableContentGuideのドキュメントを見ると、従われるルールが3つあります:

  • The readable content guide never extends beyond the view’s layout margin guide.
  • The readable content guide is vertically centered inside the layout margin guide.
  • The readable content guide’s width is equal to or less than the readable width defined for the current dynamic text size.

1つめと2つめのルールは既に説明しましたが、3つめはまだでした。上記の表の数字はアクセシビリティ設定で標準のフォントサイズが選択されている場合の値です。もっと大きいフォントサイズが選ばれている場合、読みやすい幅が(マージン内で)広くなります。もっと小さいフォントサイズが選ばれている場合、読みやすい幅が狭くなります。

別の言い方をすると、iOSの「読みやすい幅」の制限が行のポイント数ではなく、その行に入れる文字数と言えるかもしれません。

Dynamic Type対応を既にしてあるアプリは幅が選ばれたフォントサイズに合わせられた方が綺麗に表示されますが、Dynamic Type対応をしていないアプリは大きいフォントサイズが選択されている場合表示が少し読みづらくなりそうです。

ユーザーの選んだフォントサイズカテゴリはUIApplication.shared.preferredContentSizeCategoryで取れます。カテゴリが多いので、どう変わるのかのスクリーンショットは標準サイズ(large)、一番小さいサイズ(extraSmall)、「さらに大きな文字」が有効になっていない場合の一番大きいサイズ(extraExtraExtraLarge)、「さらに大きな文字」が有効になっている場合の一番大きいサイズ(accessibilityExtraExtraExtraLarge)だけのにしました。

  • large (標準設定) f:id:vincentisambart:20181206092236p:plain
  • extraSmall f:id:vincentisambart:20181206092208p:plain
  • extraExtraExtraLarge f:id:vincentisambart:20181206092011p:plain
  • accessibilityExtraExtraExtraLarge f:id:vincentisambart:20181206091716p:plain

読みやすい幅のまとめ表

Dynamic Typeの設定によって読みやすい幅の数字をまとめてみました。上記のスクリーンショット同様4つのカテゴリだけに絞りました。

どう変わるのか見せるために明確な数字を載せていますが、その明確な数字をビューの配置のために使わないでおきましょう。今後iOS端末の画面サイズの種類がまた増えても不思議ではありませんし、今後iOSのメジャーアップデートで数字が少し変わる可能性もあります。ビューをpixel perfectで配置できていた時代はもう終わっています。

iPhone SE

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 320 pt 288 pt 32 pt 16 pt
large 568 pt 528 pt 40 pt 20 pt
extraSmall 320 pt 288 pt 32 pt 16 pt
extraSmall 568 pt 528 pt 40 pt 20 pt
extraExtraExtraLarge 320 pt 288 pt 32 pt 16 pt
extraExtraExtraLarge 568 pt 528 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 320 pt 288 pt 32 pt 16 pt
accessibilityExtraExtraExtraLarge 568 pt 528 pt 40 pt 20 pt

フォントサイズが変わっても、読みやすい幅は変わらないようですね。

iPhone 8

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 375 pt 343 pt 32 pt 16 pt
large 667 pt 627 pt 40 pt 20 pt
extraSmall 375 pt 343 pt 32 pt 16 pt
extraSmall 667 pt 560 pt 107 pt 53 pt
extraExtraExtraLarge 375 pt 343 pt 32 pt 16 pt
extraExtraExtraLarge 667 pt 627 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 375 pt 343 pt 32 pt 16 pt
accessibilityExtraExtraExtraLarge 667 pt 627 pt 40 pt 20 pt

縦向きの場合、フォントサイズが変わっても、読みやすい幅は変わらないようですが、横向きだと(少し余裕あるので)少し変わるようです。

iPhone 8 Plus

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 414 pt 374 pt 40 pt 20 pt
large 736 pt 696 pt 40 pt 20 pt
extraSmall 414 pt 374 pt 40 pt 20 pt
extraSmall 736 pt 560 pt 176 pt 88 pt
extraExtraExtraLarge 414 pt 374 pt 40 pt 20 pt
extraExtraExtraLarge 736 pt 696 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 414 pt 374 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 736 pt 696 pt 40 pt 20 pt

iPhone 8同様、縦向きの場合、フォントサイズが変わっても、読みやすい幅は変わらないようですが、横向きだと(少し余裕あるので)少し変わるようです。

iPhone Xs

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 375 pt 343 pt 32 pt 16 pt
large 812 pt 772 pt 40 pt 20 pt
extraSmall 375 pt 343 pt 32 pt 16 pt
extraSmall 812 pt 560 pt 252 pt 126 pt
extraExtraExtraLarge 375 pt 343 pt 32 pt 16 pt
extraExtraExtraLarge 812 pt 772 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 375 pt 343 pt 32 pt 16 pt
accessibilityExtraExtraExtraLarge 812 pt 772 pt 40 pt 20 pt

iPhone 8同様、縦向きの場合、フォントサイズが変わっても、読みやすい幅は変わらないようですが、横向きだと(少し余裕あるので)少し変わるようです。

iPhone Xr、iPhone Xs Max

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 414 pt 374 pt 40 pt 20 pt
large 896 pt 672 pt 224 pt 112 pt
extraSmall 414 pt 374 pt 40 pt 20 pt
extraSmall 896 pt 560 pt 336 pt 168 pt
extraExtraExtraLarge 414 pt 374 pt 40 pt 20 pt
extraExtraExtraLarge 896 pt 856 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 414 pt 374 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 896 pt 856 pt 40 pt 20 pt

他のiPhone同様、縦向きの場合、フォントサイズが変わっても、読みやすい幅は変わらないようですが、横向きの場合、フォントサイズによって(もう少し余裕あるので)それなりに変わるようです。

iPad

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 768 pt 672 pt 96 pt 48 pt
large 1024 pt 672 pt 352 pt 176 pt
extraSmall 768 pt 560 pt 208 pt 104 pt
extraSmall 1024 pt 560 pt 464 pt 232 pt
extraExtraExtraLarge 768 pt 728 pt 40 pt 20 pt
extraExtraExtraLarge 1024 pt 896 pt 128 pt 64 pt
accessibilityExtraExtraExtraLarge 768 pt 728 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 1024 pt 984 pt 40 pt 20 pt

小さめなフォントサイズの場合、縦向きと横向きでは幅が同じですが、大きめなフォントサイズの場合そういうわけでもありませんね。

iPad Pro 11"

preferred content size category 向き 画面全幅③ 読みやすい
最大幅④
余白
(③-④)
左右マージン
((③-④)/2)
large 834 pt 672 pt 162 pt 81 pt
large 1194 pt 672 pt 522 pt 261 pt
extraSmall 834 pt 560 pt 274 pt 137 pt
extraSmall 1194 pt 560 pt 634 pt 317 pt
extraExtraExtraLarge 834 pt 794 pt 40 pt 20 pt
extraExtraExtraLarge 1194 pt 896 pt 298 pt 149 pt
accessibilityExtraExtraExtraLarge 834 pt 794 pt 40 pt 20 pt
accessibilityExtraExtraExtraLarge 1194 pt 1154 pt 40 pt 20 pt

通常のiPad同様、小さめなフォントサイズの場合、縦と横では幅が同じですが、大きめなフォントサイズの場合そういうわけでもありませんね。

セル

一番上に載せたiOSの設定画面の例もTwitterの例もテーブルでした。Twitterの方は左右の余白でもセルがタッチに反応するので、読みやすい幅に合わせられたのはテーブル自体ではなく、セル内のコンテンツでしょう。

セルの場合、普通のビューと少し違うところあるので、それを見ましょう。

UITableView

UITableViewのセルの挙動は他のビューと同じです: - コードでビューを配置する場合、readableContentGuideを使えます。 - Interface Builderを使う場合、制約はマージンに対して定義し、親ビュー(おそらくcontent view)のレイアウト設定の「Follow Readable Width」にチェックを入れたら読みやすい幅に合わせられます。

でも、よりよい方法として、UITableViewcellLayoutMarginsFollowReadableWidthというプロパティを使う方法もあります。Interface Builderでは、UITableViewの「Follow Readable Width」にチェックを入れるのと同じです。

cellLayoutMarginsFollowReadableWidthは自分が定義したカスタムセルだけではなく、テーブルの区切り線にもUIKitが提供しているカスタムでないCellStyleにも影響しています。

いくつかのセルCellStyleの一例、cellLayoutMarginsFollowReadableWidthfalseの場合: f:id:vincentisambart:20181206092608p:plain

cellLayoutMarginsFollowReadableWidthtrueの場合: f:id:vincentisambart:20181206092711p:plain

因みにcellLayoutMarginsFollowReadableWidthtrueの場合、content viewのlayoutMarginsGuidereadableContentGuideのどっちを使っても同じことになります。

UICollectionView

UICollectionViewに全幅に渡るセルがあれば、読みやすい幅を使いたくなることあるかもしれません。ただ、UICollectionViewにはcellLayoutMarginsFollowReadableWidthのようなプロパティがありません。

コードではreadableContentGuideは使えますが、Interface Builderでセル(実質セルのcontent view)のレイアウト設定の「Follow Readable Width」にチェックを入れても効果がありません(バグ)。でもワークアラウンドとしてcontent viewの中にビューを入れ、そのビューの「Follow Readable Width」にチェックを入れ、他のビューをその中に入れ、制約をそのビューのマージンに対して定義すれば動くようです。

まとめ

iOSでは、対応すべき画面サイズが少しずつ増えています。先日発表された新しいiPad Proも以前のと画面サイズが少し変わりました。事前に分かっている数少ない画面サイズを元にアプリの配置を決められる時代が終わっています。

その中でできるだけ多くの画面サイズに合わせて綺麗に配置できるツールの1つとして、読みやすい幅、または読みやすいコンテンツ、というのがあります。

読みやすいコンテンツを使うときはドキュメントにも書いてある3つのルールを覚えておきましょう:

  • readableContentGuideが自分のビューのlayoutMarginsGuide外に出ることはありません。
  • readableContentGuideが水平方向でlayoutMarginsGuideの中央にあります。
  • readableContentGuideの幅が選ばれたDynamic Typeのフォントサイズ次第で決まる読みやすい幅以下です。
/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('https://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/