SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

iOS16の新機能に触れてみよう

iOS16/SwiftUI4の新しいデータ共有とUIの表示形式をサンプルと共に学ぶ

iOS16の新機能に触れてみよう 第2回

より高度な表現が可能となった──Graphics and Layout

 プログラムでの処理の向上のほかに、UIの外観や表示形式についても機能が充実しました。主要な変更点について、Shape Style/Layoutの2つでまとめられています。

SwiftUI 4での主要な変更点
ジャンル 概要
Shape Style UIの外観
Layout 画面レイアウト

 それぞれの項目について簡単なサンプルコードとともに紹介します。

Shape Style

 UIの前景スタイル(foregroundStyle)と背景スタイル(backgroundStyle)を指定できるようになりました。前景スタイルには色や影などの装飾、背景スタイルには背景として画像/色/グラデーションなどを指定することができます。

[リスト5]ShapeStyleSample/ContentView.swift抜粋
struct ContentView: View {
    var body: some View {
        Image(systemName: "swift")
            .frame(width: 150,height: 150)
            .background(in: Circle())
            .foregroundStyle(.white.shadow(.drop(color:.black, radius:2, x:4, y:4)))    // -------- ①
            .backgroundStyle(.orange.gradient)    // -------- ②
            .font(.system(size:60))
    }
}
Shape Styleの例
Shape Styleの例

 最初にSwiftのアイコン画像を円の形状で用意します。ここにforegroundStyleメソッドでアイコンの色を白、黒い影をつけます(①)。影をつけるときには、色/影のエフェクト/オフセットを指定することができます。その後にbackgroundStyleメソッドで、オレンジのグラデーションで背景色をつけます。サンプルのようにロゴ画像のような外観を簡単に実現できるようになりました。

Layout

 動的にレイアウトを変更するAnyLayoutとグリッド表示を行うGridという新しい仕様が追加されました。具体的なサンプルをあげて説明します。

AnyLayout

 AnyLayoutはレイアウトを動的に変更できるプロトコルです。画面上に配置済みのビューを破棄することなどはなく、動的にレイアウトを変更できます。AnyLayoutを利用してレイアウトを動的に変更するサンプルは次のとおりです。

[リスト6]AnyLayoutSample/ContentView.swift抜粋
struct ContentView: View {
     // レイアウトを切り替えるフラグ
    @State var isChangeLayout: Bool = false
    // 前節のサンプルで作成したImage
    let image: some View = Image(systemName: "swift")
        .frame(width: 150,height: 150).font(.system(size:60))
        .background(in: Circle()).backgroundStyle(.orange.gradient)
        .foregroundStyle(.white.shadow(.drop(color:.black, radius:2, y:4)))
    
    var body: some View {
        VStack {
        	// 動的に変更するレイアウトを定義
            let layout: AnyLayout = isChangeLayout ? AnyLayout(HStackLayout()) : AnyLayout(VStackLayout())   // -------- ①
            // Imageを2つ並べてタップでレイアウトを変更
            layout {
                image
                image
            }
            .padding()
            .animation(.spring(), value: isChangeLayout)
            .onTapGesture {    // --------②
                isChangeLayout.toggle()
            }
        }
    }
}
Layoutの例
Layoutの例

 バインディング変数isChangeLayoutの値によって水平方向または垂直方向のAnyLayoutを定義します。AnyLayoutの定義には、条件付きの水平方向レイアアウトを定義するHStackLayout構造体、条件付きの垂直方向レイアアウトを定義するVStackLayout構造体を利用します。プレビュー画面とともに利用するHStack/VStackの構造体ではないことに気を付けてください。onTapGestureメソッドで、タップ時にisChangeLayoutの値を切り替わり、レイアウトもアニメーションを伴って切り替わります(②)。

Grid

 Gridは、グリッドの形式で表示を行う構造体です。Gridブロック内にGridRow構造体を配置することで、行単位での表示を指定することができます。Gridを使った簡単なサンプルは次のとおりです。

[リスト7]GridListSample/ContentView.swift抜粋
struct SquareView: View { // グリッドのセルに表示するビューを定義
    let color: Color
    var body: some View {
        color.frame(width: 50, height: 50)
    }
}

struct ContentView: View {
    var body: some View {
        Grid {  // -------- ①
             // 赤5セルを表示
            GridRow {    // --------②
                ForEach(0..<5) { _ in
                    SquareView(color: .red)
                }
            }
            // 青3セルを空白を挟んで表示
            GridRow {    // --------②
                SquareView(color: .blue)
                Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])    // --------③
                SquareView(color: .blue)
                Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])   // --------③
                SquareView(color: .blue)
            }
            // 緑3セルを中央に詰めて表示
            GridRow {    // --------②
                Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])   // --------③
                ForEach(0..<3) { _ in
                    SquareView(color: .green)
                }
                Color.clear.gridCellUnsizedAxes([.horizontal, .vertical])   // --------③
            }
        }
    }
}
Gridの例
Gridの例

 グリッドは、Gridブロック(①)の中にGridRowブロックを行を設ける(②)ことで表示できます。グリッドのセルを空けたい場合は、色やビューで必要なスペースを埋めるgridCellUnsizedAxesメソッドを利用します(③)。

 またGridブロックは、一定の領域を確実に表示するという性質を利用して、表を作成するという使い方もできます。連載第1回で紹介した複数のリストをまとめるTableはiOSには未対応です。Gridをうまく使うと、iOSでも複数のリストをまとめて表示することができます。Gridを利用して、月当たりの売り上げデータを表にするサンプルは次のようになります。

[リスト8]GridListSample/ContentView.swift抜粋
struct ContentView: View {
    var body: some View {
        Grid(alignment: .leading, horizontalSpacing: 0, verticalSpacing: 10) { // -------- ①
            ForEach(MonthAmount.examples) { item in
                GridRow(alignment: .firstTextBaseline) { // -------- ②
                    Text(item.month)
                    Text("\(item.amount)")
                }.padding([.leading, .trailing])
                GridRow {
                    Rectangle().frame(height: 1).gridCellColumns(2) // -------- ③
                }
            }
        }
    }
}
Gridの例
Gridの例

 Grid構造体自体には、セルを揃える基準/水平方向のスペース/垂直方向のスペースを指定することができます(①)。Gridブロックの中で、月当たりの売り上げデータをForEachでループします。最初に月名と売り上げを表示します(②)。その後に、高さを1として矩形をグリッドのセルを統合するgridCellColumnsメソッドで2セル分配置します(③)。ループが終わると、月当たりの売り上げデータが表で表示されます。

まとめ

 今回は「What's new in SwiftUI」の後半部分で紹介されたSwiftUI 4の新しい機能について説明しました。次回からSwiftUI 4の機能を使ったもう少し実用的なサンプルを作成していきます。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
iOS16の新機能に触れてみよう連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 片渕 彼富(カタフチ カノトミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/16719 2022/11/21 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー