【SwiftUI】Circleくん、君は丸の形をした何者なんだい?

2022.04.23

SwiftUIでVStackを使用してCircle()を上寄せにしたかったのに思ったような挙動にならなかったので原因を調べてみました。

環境

  • Xcode 13.3

事象

コード

VStackSpacer()を組み合わせることでCircle()を上詰したいと思っています。

struct ContentView: View {
    var body: some View {
        VStack {
            Circle()
                .frame(width: 30)

            Spacer()
        }
    }
}

結果

上詰されませんでした。

調査

コード

backgroundに色を付けてみました。

struct ContentView: View {
    var body: some View {
        VStack {
            Circle()
                .frame(width: 30)
                .background(.red)

            Spacer()
        }
    }
}

結果

backgroundに色を付けてみると、Circle30 × 30の円の形のように振る舞うも実際のViewとしてはframeが設定されていない高さの方向には画面いっぱいに広がっていました。

Rectangleの場合

Rectangleで試してみると縦方向はしっかり画面いっぱいに表示されました。

コード

var body: some View {
    VStack {
        Rectangle()
            .frame(width: 30)

        Spacer()
    }
}

結果

Circleもこんな感じに縦方向に広がってくれたらよかったのですが、、

原因

Circleが見た目上は30 × 30の円の形のように振る舞うも、実際のViewとしてはwidth30だが、heightは画面いっぱいに広がっていたのが原因だった。 CircleがViewとしては縦方向画面いっぱいに広がっている為、VStackSpacer()を併用して上詰にしようとしても出来なかった。

解決法

frameで幅も高さも指定してあげると意図した挙動になりました。 CircleRectangleとは違って指定していない高さ(または幅)方向にViewとしては広がっているけど、見た目上は広がっていないように見せてくるので幅と高さを指定していないとふとした時にハマりそうですね。

コード

var body: some View {
    VStack {
        Circle()
            .frame(width: 30, height: 30)

        Spacer()
    }
}

結果

まとめ

Circleも、VStackSpacerと同じように可能な限り広がろうとするViewであることが分りました。今回Circleくんに出会えたことでまた少しSwiftUIのレイアウトシステムについて理解出来たような気がします。

SwiftUIをしているとPaddingが意図したように表示されてないや、今回のようにStackやSpacerがうまく機能していないと思う時は、.backgroundモディファイアを使用してViewに色付けすることで実際どうなっているのか可視化すると問題解決の糸口を見つけやすくなりそうだなと感じたので、今後試していきたいと思います!

Circleくん、君に会えてよかった。

参考