🕊️

SwiftUIによるアコーディングリスト実装

に公開

1. はじめに

SwiftUIを使ったアコーディオンリスト(折りたたみ可能なリスト)の実装方法について紹介します。アコーディオンUIはユーザーインターフェースをすっきりと保ちながら、必要な情報を表示できる便利なUIパターンであるため、モバイルアプリのような限られた表示範囲内に情報を表示する際には持ってこいだと思いますので、ぜひ参考にして下さい。

2. アコーディオンリストとは

アコーディオンリストは、タップすると詳細情報が展開/折りたたみされるUIコンポーネントです。限られた画面スペースを効率的に使いながら、ユーザーが必要な情報にアクセスできるようにする優れた方法です。

3. 実装方法

今回の実装では、以下のコンポーネントを作成します。

  1. データモデル(Item
  2. 個別のアコーディオンアイテム(AccordionItem
  3. アコーディオンリスト全体(AccordionList

データモデルの定義

まず、リストに表示するアイテムのデータモデルを定義します。

struct Item: Identifiable {
    let id = UUID()
    let title: String
    let description: String
}

Identifiable プロトコルに準拠することで、ForEach でリスト表示する際に各アイテムを一意に識別できるようになります。

サンプルデータの準備

テスト用にサンプルデータを作成しておきます。

let sampleItems = [
    Item(title: "項目1", description: "これは項目1の詳細説明です。タップすると表示されます。"),
    Item(title: "項目2", description: "これは項目2の詳細説明です。長いテキストも問題なく表示できます。SwiftUIは自動的にレイアウトを調整します。"),
    Item(title: "項目3", description: "これは項目3の詳細説明です。アコーディオン機能を使うとユーザーインターフェースをすっきりと保ちながら、必要な情報を表示できます。")
]

アコーディオンアイテムの実装

次に、個々のアコーディオンアイテムを表示するビューコンポーネントを実装します。

struct AccordionItem: View {
    let item: Item
    @State private var isExpanded = false
    
    var body: some View {
        VStack(alignment: .leading) {
            Button(action: {
                withAnimation {
                    isExpanded.toggle()
                }
            }) {
                HStack {
                    Text(item.title)
                        .font(.headline)
                        .foregroundColor(.primary)
                    
                    Spacer()
                    
                    Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
                        .foregroundColor(.gray)
                }
                .padding(.vertical, 10)
            }
            
            if isExpanded {
                Text(item.description)
                    .font(.body)
                    .foregroundColor(.secondary)
                    .padding(.bottom, 10)
                    .transition(.opacity)
            }
        }
        .padding(.horizontal)
        .background(Color(.systemBackground))
        .cornerRadius(8)
        .overlay(
            RoundedRectangle(cornerRadius: 8)
                .stroke(Color.gray.opacity(0.2), lineWidth: 1)
        )
    }
}

💡ここでのポイント

  • @State private var isExpanded = falseでアイテムの展開状態を管理
  • ButtonのアクションでisExpanded.toggle()を呼び出し、状態を切り替えwithAnimation { }で状態変更時にアニメーションを適用
  • 条件付きでif isExpanded { }内のコンテンツを表示
  • .transition(.opacity)で表示/非表示の切り替え時にフェードイン/アウト効果を追加
  • 見た目を整えるために.overlayでボーダーを追加

アコーディオンリスト全体の実装

最後に、複数のアコーディオンアイテムをリスト表示するビューを実装します。

struct AccordionList: View {
    let items: [Item]
    
    var body: some View {
        ScrollView {
            VStack(spacing: 12) {
                ForEach(items) { item in
                    AccordionItem(item: item)
                }
            }
            .padding()
        }
    }
}

ScrollViewVStack を組み合わせることで、アイテム数が多くても問題なく表示できるようにしています。

使用方法

実装したアコーディオンリストをアプリで使用するには、以下のようにします。

struct ContentView: View {
    var body: some View {
        AccordionList(items: sampleItems)
            .padding()
    }
}

アコーディオンリスト実行動画

カスタマイズのアイデア

基本的な実装ができたら、以下のようなカスタマイズを検討してみてください。

  1. カラーテーマの変更

    // AccordionItemの中で
    .background(Color.blue.opacity(0.1))
    .overlay(
        RoundedRectangle(cornerRadius: 8)
            .stroke(Color.blue.opacity(0.3), lineWidth: 1)
    )
    
  2. アニメーションの調整

    withAnimation(.spring()) {
        isExpanded.toggle()
    }
    
  3. アイコンの変更

    Image(systemName: isExpanded ? "minus.circle" : "plus.circle")
    
  4. 展開時のコンテンツをカスタマイズ

    if isExpanded {
        VStack(alignment: .leading, spacing: 8) {
            Text(item.description)
            
            Button("詳細を見る") {
                // アクション
            }
            .padding(.top, 4)
        }
        .transition(.opacity)
    }
    

4. まとめ

SwiftUIを使ったアコーディオンリストの実装は、@State変数で展開状態を管理し、条件付きビューで内容の表示/非表示を切り替えるというシンプルなアプローチで実現できます。アニメーションも簡単に追加でき、UIの見た目も自由にカスタマイズ可能です。

SwiftUIの宣言的なコード記述と状態管理の仕組みを活用することで、少ないコード量でインタラクティブなUIを実現できることがお分かりいただけたと思います。ぜひ実際に試してみて、より使いやすいアプリ開発にお役立てください。

Discussion