中学数学621382 views
中学英語808712 views
英語607877 views
小学理科717236 views
小学算数1194618 views
Computer365120 views
高校生物549842 views
LaTeX957300 views
高校日本史189857 views
高校倫理1433119 views
Help
Tools

English

カスタム行のデザイン

List のデフォルト表示では物足りない場合、カスタム行を作成して独自のデザインを実現できます。再利用可能なコンポーネントとして切り出す方法も含めて解説します。

基本的なカスタム行

List の各行には任意の SwiftUI ビューを配置できます。HStack を使って横並びのレイアウトを作るのが基本パターンです。

struct ContentView: View {
    var body: some View {
        List {
            HStack {
                Image(systemName: "person.circle.fill")
                    .font(.title)
                    .foregroundColor(.blue)
                
                VStack(alignment: .leading) {
                    Text("山田太郎")
                        .font(.headline)
                    Text("yamada@example.com")
                        .font(.subheadline)
                        .foregroundColor(.gray)
                }
                
                Spacer()
                
                Image(systemName: "chevron.right")
                    .foregroundColor(.gray)
            }
        }
    }
}

再利用可能な行コンポーネント

同じデザインの行を複数箇所で使う場合は、別のビューとして切り出します。

struct UserRow: View {
    let user: User
    
    var body: some View {
        HStack {
            Image(systemName: "person.circle.fill")
                .font(.title)
                .foregroundColor(.blue)
            
            VStack(alignment: .leading) {
                Text(user.name)
                    .font(.headline)
                Text(user.email)
                    .font(.subheadline)
                    .foregroundColor(.gray)
            }
        }
    }
}

struct User: Identifiable {
    let id = UUID()
    var name: String
    var email: String
}

struct ContentView: View {
    let users = [
        User(name: "山田太郎", email: "yamada@example.com"),
        User(name: "佐藤花子", email: "sato@example.com")
    ]
    
    var body: some View {
        List(users) { user in
            UserRow(user: user)
        }
    }
}

複雑なレイアウトの行

画像、タイトル、サブタイトル、バッジなどを含む複雑な行も自由に作成できます。

struct ProductRow: View {
    let product: Product
    
    var body: some View {
        HStack(spacing: 12) {
            // 商品画像
            RoundedRectangle(cornerRadius: 8)
                .fill(Color.gray.opacity(0.3))
                .frame(width: 60, height: 60)
                .overlay {
                    Image(systemName: "photo")
                        .foregroundColor(.gray)
                }
            
            // 商品情報
            VStack(alignment: .leading, spacing: 4) {
                Text(product.name)
                    .font(.headline)
                
                Text(product.category)
                    .font(.caption)
                    .foregroundColor(.secondary)
                
                HStack {
                    Text(\(product.price)")
                        .font(.subheadline)
                        .fontWeight(.bold)
                        .foregroundColor(.blue)
                    
                    if product.isOnSale {
                        Text("SALE")
                            .font(.caption2)
                            .fontWeight(.bold)
                            .foregroundColor(.white)
                            .padding(.horizontal, 6)
                            .padding(.vertical, 2)
                            .background(Color.red)
                            .cornerRadius(4)
                    }
                }
            }
            
            Spacer()
        }
        .padding(.vertical, 4)
    }
}

行のパディング調整

List は自動的に行にパディングを追加します。これを調整したい場合は listRowInsets モディファイアを使います。

List {
    HStack {
        Color.blue
        Text("端から端まで")
    }
    .listRowInsets(EdgeInsets())  // パディングをゼロに
}
listRowInsets

行の内側の余白を調整する。EdgeInsets() を渡すとパディングがゼロになる。

listRowBackground

行の背景色やビューをカスタマイズする。

listRowSeparator

区切り線の表示・非表示を制御する。

条件付きスタイリング

データの状態に応じて行の見た目を変えることもできます。

struct TaskRow: View {
    let task: Task
    
    var body: some View {
        HStack {
            Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
                .foregroundColor(task.isCompleted ? .green : .gray)
            
            Text(task.title)
                .strikethrough(task.isCompleted)
                .foregroundColor(task.isCompleted ? .gray : .primary)
        }
    }
}

カスタム行を作成する際は、再利用性を意識してビューを分割し、データモデルと表示ロジックを明確に分離することがポイントです。