9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftAdvent Calendar 2021

Day 13

[Swift] Compositional Layouts で Readable Width の対応をする

Last updated at Posted at 2021-12-12

前置き

多くの会社で Compositional Layouts を使っているところが増えてきたのではないでしょうか?

今回は Compositional Layouts におけるiPad対応(Readable Width)を考えてみました。実際のリリースしているプロダクションの事例を元に紹介していきたいと思います。

考察

1. 既存の方法

実装方法によって対応方法が変わってきます。

① デフォルトのUITableView のセルは cellLayoutMarginsFollowReadableWidthtrue にすることで対応可能です。

.swift
tableView.cellLayoutMarginsFollowReadableWidth = true

Interface Builder で行う場合、親のViewFollow Readable Width にチェックをつけ、Constraintsを調整することで対応が可能です。

check

Autolayout で行う場合、readableContentGuide に設定することで対応できます。

.swift
NSLayoutConstraint.activate([
    tableView.leadingAnchor.constraint(equalTo: readableContentGuide.leadingAnchor),
    tableView.trailingAnchor.constraint(equalTo: readableContentGuide.trailingAnchor)
])

↓ 具体的な実装事例はこちらを参考にすると良いでしょう

2. 既存の問題点

Compositional Layoutsを導入した画面に既存の方法を取り入れた場合、先程の ② or ③ で UICollectionView の全体に Constraints を設定することになるかと思います。

この方法は、数行のコードで済み、メンテナンスしやすいですが、スクロールのタップ範囲が狭まってしまうという問題があります。

  • 動作例

scroll.gif

この場合、左右スクロールバーより外は触っても何もスクロールが起きません。

まだ、iPadのデザイン対応が間に合っていない場合に、恒久対応としてはすぐに導入するくらいの温度感が良いでしょう。

3. Compositional Layouts での対応方法

Compositional Layouts は コードのframeでレイアウトを設定していくので、これに合わせて幅を調整していくことになります。

.swift
// 画面幅
let viewWidth = view.frame.width

// 端末ごとの readable width を取得
let readableWidth = view.readableContentGuide.layoutFrame.width

// 左右のマージン
let margin = (viewWidth - readableWidth) / 2

// 横幅の最大値
let dimension: NSCollectionLayoutDimension = .absolute(readableWidth)

画面から readableContentGuidelayoutFrame が取得でき、ここから各端末の readable width を取得することができます。また、中央寄せにするために、左右のマージンを差分から計算します。

実際に設定するコード例としてはこのような形です。

.swift
let item = NSCollectionLayoutItem(layoutSize: .init(
    widthDimension: .fractionalWidth(1),
    heightDimension: .fractionalHeight(1)
))

let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(
    widthDimension: .absolute(readableWidth), // readableな横幅を指定する
    heightDimension: .absolute(100)
), subitem: item, count: 3)

let section = NSCollectionLayoutSection(group: group)
section.contentInsets = .init(top: 0, leading: margin, bottom: 0, trailing: margin) // 中央寄せ

sectioncontentInsets を調整することで中央寄せにしています。


  • プロダクションでの画面例

diff

このように frame を操作することで Compositional Layouts でも iPad の readable width に対応することが可能となります。

4. iOS14 以降

ここまで実装方法を書いてきましたが、iOS14 以降の Compositional Layouts では contentInsetsReference で設定するだけで済みます。

Screen Shot

終わりに

iPad 対応は後回しにされがちですが、そこまで手間もかからず実装できるので、是非試してみて欲しいです。

皆さんも iPad 対応をすることで、快適な iPad ライフを実現しましょう!

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?