メインコンテンツへスキップ
見出し画像

SwiftUIでサイズクラスに応じてレイアウトを変える

    Size Classとは、iOS開発における様々なデバイスや向きに対応したAdaptiveレイアウトを実現する上での重要な概念であり、今回はSwiftUIでSize Classを使ってレイアウトを変える方法を簡単に紹介する。

    Size Classの細かい定義はHuman Interface Guidelinesに記載されているが、ざっくり以下の組み合わせとなっている。 ※Size ClassはiPadでのSplit Viewにも適用される

    画像

    SwiftUIでSize Classを使う

    Size ClassはEnrivonment property wrapperを使って以下のように定義できる(こちらを参照)。

    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    

    horizontalSizeClass, verticalSizeClassは以下のようなEnum値を取るので、body内で条件分岐してレイアウトを切り替えることができる。

    public enum UserInterfaceSizeClass {
        case compact
        case regular
    }
    

    以下のコードでは、予め縦向きや横向きのレイアウトを定義し、条件分岐でそれぞれのレイアウトを切り替えることでAdaptiveレイアウトを実現している。ただし、iPadでは縦横ともにRegularとなってしまうので、iPadの縦横画面でレイアウトを変更したい場合は、画面回転の検知など別のアプローチも必要となる。 ※if文による記述は長いので、こちらの記事のようにSize Classの組み合わせでEnumを定義してもよい。

    struct ContentView: View {
        
        @Environment(\\.horizontalSizeClass) private var horizontalSizeClass
        @Environment(\\.verticalSizeClass) private var verticalSizeClass
        
        var body: some View {
            if (horizontalSizeClass == .regular && verticalSizeClass == .compact) ||
               (horizontalSizeClass == .compact && verticalSizeClass == .compact) {
                // Landscape (iPhone)
                landscapeLayout
            } else if horizontalSizeClass == .compact && verticalSizeClass == .regular {
                // Portrait (iPhone)
                portraitLayout
            } else {
                // iPad
                landscapeLayout
            }
        }
    }
    
    private extension ContentView {
        /// 縦向きのレイアウト
        var portraitLayout: some View {
            VStack {
                Color(UIColor.red).frame(width: 200, height: 200)
                Color(UIColor.green).frame(width: 200, height: 200)
                Color(UIColor.blue).frame(width: 200, height: 200)
            }
        }
        
        /// 横向きのレイアウト
        var landscapeLayout: some View {
            HStack {
                Color(UIColor.red).frame(width: 200, height: 200)
                Color(UIColor.green).frame(width: 200, height: 200)
                Color(UIColor.blue).frame(width: 200, height: 200)
            }
        }
    }
    
    画像

    参照


     
     

    TAAT

     
     
    Software Engineer / iOS, visionOS, Unity / Metaverse, Spatial Computing, AI Coding / VRoid

    あなたへのおすすめ