すらぼうの開発ノート

モバイルアプリエンジニアのメモ

【SwiftUI】aspectRatio()メソッドに渡す.fitと.fillの違い

aspectRatio()メソッドに渡す.fitと.fillの違いについて説明する。

違い

.fit

指定された領域内にオブジェクトが収まるように表示される。

.fill

指定された領域内をオブジェクトが埋め尽くすように表示される。


少し詳しく

aspectRatio()メソッド

オブジェクトの縦横比を設定する役割を持つメソッド。

developer.apple.com

定義は以下の様になっており、

func aspectRatio(
    _ aspectRatio: CGSize,
    contentMode: ContentMode
) -> some View

.fitないしは.fillを渡すのはcontentModeになる。 なので使用する際には

何かのオブジェクト
.aspectRatio(contentMode: .fill ないしは .fill)

という形式になる。

図例

書籍などではImage構造体を使用する際によく使用される。 なので今回は以下の画像を用い、どの様に.fitと.fillで表示が異なるのかを図で示す。

チンアナゴ

この画像を縦横それぞれ300の正方形に表示してみる。 frameの領域がわかりやすいように枠線を表示させる。

Image("anago")
  .resizable()
  .frame(height: 300, width: 300)
  .border(Color.black, width: 1)

このままだと以下のように表示される。

.fit

画像が枠内に収まる様にaspectRatio(contentMode: .fit)を適用してみると次の様になる。

Image("anago")
  .resizable()
  .aspectRatio( contentMode: .fit)
  .frame(height: 300, width: 300)
  .border(Color.black, width: 1)

.fitを適用

.fill

画像がframe領域を埋め尽くす様にaspectRatio(contentMode: .fill)を適用してみると次の様になる。

Image("anago")
  .resizable()
  .aspectRatio( contentMode: .fill)
  .frame(height: 300, width: 300)
  .border(Color.black, width: 1)

.fillを適用

このままだとチンアナゴの顔がframe領域に収まっておらずかわいそうなので、画像を下方向へずらしたい。 そんな時にはoffset()メソッドを使うとよい。

Image("anago")
  .resizable()
  .aspectRatio( contentMode: .fill)
  .offset(y: 50)
  .frame(height: 300, width: 300)
  .border(Color.black, width: 1)

チンアナゴの顔が枠内に収まった

またclipped()メソッドを適用すると、枠外にはみ出た部分を非表示にしてくれる。

Image("anago")
  .resizable()
  .aspectRatio( contentMode: .fill)
  .offset(y: 50)
  .frame(height: 300, width: 300)
  .border(Color.black, width: 1)
  .clipped()

clipped()を適用