【SwiftUI】AppデザインのためにGeometryReaderを理解する


はじめに

SwiftUIでそれぞれのViewのレイアウトをデザインする時に必要なGeometryReaderについて整理することを目的とする

開発環境

OSX 10.15.7 (Catalina)
Xcode 12.2.0
CocoaPods 1.10.0

SwiftUIのレイアウトシステム

Appをデザインするための基本的な考え方はHStack、VStack、ZStackを組み合わせです。複雑なレイアウトを実装していくためにそれぞれの特徴を理解する必要があります。

  • HStack
    childViewを横一列に並べることができる。
    "H": a horizontal line

  • VStack
    childViewを縦方向に並べることができる。
    "V": a vertical line

  • ZStack
    childViewを重ねることができる。
    "Z": overlap

参考文献
How to use stacks: HStack, VStack and ZStack in SwiftUI (Equivalent of UIStackView in UIKit)

import SwiftUI

struct ContentView: View {
    var body: some View {

        // a vertical line
        VStack {

            // a vertical line
            VStack {

                // overlap
                ZStack {

                    // a horizontal line
                    HStack{

                        Image(systemName: "doc")
                        Text("First One")
                    }

                }
                // overlap
                ZStack {

                    // a horizontal line
                    HStack{

                        Image(systemName: "doc")
                        Text("Two One")
                    }
                }
            }
        }
    }
}

GeometryReaderの考え方

参考文献

GeometryReaderはViewの一種であり、親のViewのサイズと自身の親のViewに対する位置を知るためのもの

実装の要点

struct ContentView: View {
    var body: some View {

        // a vertical line
        // parent View
        VStack {
            // クロージャーの"g"は任意で設定可能
            GeometryReader { g in

                // a vertical line
                VStack {

                    // overlap
                    ZStack {

                        // a horizontal line
                        HStack{

                            Image(systemName: "doc")
                            Text("First One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/2に設定。
                    }.frame(width: g.size.width, height: g.size.height/2, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                    .background(Color.red)

                    // overlap
                    ZStack {

                        // a horizontal line
                        HStack{

                            Image(systemName: "doc")
                            Text("Two One")
                        }
                    // parentViewの幅いっぱい、縦は全体の1/2に設定。
                    }.frame(width: g.size.width, height: g.size.height/2, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                    .background(Color.yellow)
                }
            }
        }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    }
}

現在、IPhoneは様々な画面サイズのデバイスが生産されています。それらのサイズに適したデザインをするためにはGeometryReaderでサイズを取得し、配置していく必要があります。

以下のイメージは画面サイズを1/3に設定したものです。height: g.size.height/3の"3"は整数だけでなく、小数点で表記しても認識されます。これにより、さらに細かいレイアウトのデザインが可能です。

実装のイメージ

ログイン・サインアップViewのレイアウトイメージです。
全体の比率を計算して、レイアウトを決めていきます。