10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SwiftUI】カードみたいにコンテンツを表示をするときはGroupBoxを使うと便利だよ

Posted at

GroupBoxとは

今回は、SwiftUIの便利なViewのひとつ「GroupBox」を紹介します。

GroupBoxは意味のあるひとまとまりのコンテンツを視覚的にわかりやすく表示してくれるViewです。

言葉で説明するとわかりにくいので、Apple公式ドキュメントのサンプルをご覧ください。こちらのサンプルのように、カードのような見た目で表示してくれるコンポーネントです。
GroupBox | Apple Developer Documentation

スクリーンショット 2024-10-29 14.46.54.png

GroupBoxを使ってみよう

こちらのサンプルはわたしがリリースした集中アプリのFocus Rainbowです。
Screen Time APIを使って、今集中したいアプリだけを実行することができます。
便利なタイマー機能や、楽しいキャラクターが集中をサポートしてくれるので、ぜひお試しください!

Focus Rainbowではアプリの使い方のコツを紹介する画面を用意していて、その中に「自分のスマホを人に貸すときに大事なアプリをガードする」説明があります。
設定方法の手順を記載している箇所は、ひとまとまりの情報なのでスクリーンショットのように枠で囲っています。

Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.23.05.png

この部分のコードは、下記のとおりです。

    VStack(spacing: 10) {
        VStack(alignment: .leading, spacing: 20) {
            Text("1. アクティビティを追加します。")
            Text("2. アプリを選択ボタンをタップして、触っていいアプリだけを選んで登録します。")
            Text("3. 追加したアクティビティをタップして、集中するボタンをタップします。")
            Text("4. スマホを貸す時間を設定して、開始ボタンをタップします。")
            Text("5. ミッション完了!安心してスマホを渡せます。")
            Text("注意!")
                .font(.headline)
            Text("「大事なアプリをいつも使えるようにする」で紹介した方法で登録したアプリはガードされません。設定を見直すのをお忘れなく。")
        }
    }
    .padding()
    .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.accentColor, style: StrokeStyle(lineWidth: 1)))
    .clipShape(.rect(cornerRadius: 15))

では、このコードをGroupBoxに書き換えてみましょう。

    GroupBox {
        VStack(alignment: .leading, spacing: 10) {
            Text("1. アクティビティを追加します。")
            Text("2. アプリを選択ボタンをタップして、触っていいアプリだけを選んで登録します。")
            Text("3. 追加したアクティビティをタップして、集中するボタンをタップします。")
            Text("4. スマホを貸す時間を設定して、開始ボタンをタップします。")
            Text("5. ミッション完了!安心してスマホを渡せます。")
            Text("注意!")
                .font(.headline)
            Text("「大事なアプリをいつも使えるようにする」で紹介した方法で登録したアプリはガードされません。設定を見直すのをお忘れなく。")
        }
        .padding(.top)
    } label: {
        Label("設定方法", systemImage: "info.circle")
    }

GroupBoxに定義されている init(content: label:) というInitializerを使用しています。
contentにメインの情報を、labelにタイトル的な情報を設定します。

では、GroupBoxで書いたものを見てみましょう。
いい感じです。標準コンポーネントなので、ダークモード対応もバッチリですね。

ライトモード ダークモード
Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.20.50.png Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.24.03.png

GroupBoxStyleでカスタマイズ

ただ、元のサンプルとはだいぶ見た目が違うので、カスタマイズしてみましょう。
カスタマイズするときは、 GroupBoxStyle を使用します。

labelとcontentは左寄せにしたいので、VStackで囲んでalignmentを.leadingにしています。
また、アクセントカラーの枠線をつけて、角丸にしています。

struct RoundedCornerGroupBoxStyle: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        VStack(alignment: .leading) {
            configuration.label
            configuration.content
        }
        .padding()
        .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.accentColor, style: StrokeStyle(lineWidth: 1)))
        .clipShape(.rect(cornerRadius: 15))
    }
}

GroupBoxにGroupBoxStyleを適用するときは、 groupBoxStyle(_:) を使用します。

    GroupBox {
        VStack(alignment: .leading, spacing: 10) {
            Text("1. アクティビティを追加します。")
// (中略)
        }
        .padding(.top)
    } label: {
        Label("設定方法", systemImage: "info.circle")
    }
    .groupBoxStyle(RoundedCornerGroupBoxStyle())

では、さっそく結果を見比べてみましょう。
いい感じですね。元のサンプルと同じようになりました。

元のサンプル GroupBoxStyleで書いたもの
Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.23.05 2.png Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.44.58.png

まとめ

個人で開発しているアプリはできるだけAppleが提供しているコンポーネントを使って標準的なUIに近づけるように気をつけています。

標準的なUIに近いと、ユーザーは馴染みがあるのでとっつきやすくなります。また、標準のコンポーネントを使用すると、OSをアップデートしても壊れにくいですし、iPad OSやtvOSなど複数デバイス対応もやりやすくなります。

コンテンツのグループを作るときは、GroupBoxを試してみてください。

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?