If you've ever booked a flight, you're familiar with the seat map where you choose your preferred seat. In this tutorial, we'll replicate this feature using SwiftUI.
Step 1: Define the Data Model
Let's start by defining our data model:
enum SeatState {
case empty
case occupied
}
struct SeatId: Equatable, Hashable {
var row: Int
var letter: String
}
struct Seat: Identifiable, Equatable {
var id: SeatId
var state: SeatState
}
Here, each Seat has an id (consisting of its row and letter) and a state (which can be either empty or occupied).
Step 2: Create the Seat View
We need a visual representation of our seat:
struct SeatView: View {
var seat: Seat
var body: some View {
Text(seat.id.letter)
.frame(width: 40, height: 40)
.background(seat.state == .empty ? Color.green : Color.red)
.cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.black, lineWidth: 2)
)
}
}
The SeatView displays the seat letter and changes its background based on its state.
Step 3: Build the Seat Map
Our goal is a grid layout with 2 seats, an aisle with a row number, 3 seats, another aisle, and then 2 more seats:
struct FirstClassView: View {
@State var seats: [Seat] = (1..<25).map { row in
["A", "B", "C", "D", "E", "F", "G"].map { letter in
Seat(id: SeatId(row: row, letter: letter), state: .empty)
}
}.flatMap { $0 }
var columns: [GridItem] = [
.init(.flexible()), // A seat
.init(.flexible()), // B seat
.init(.fixed(40)), // Aisle with row number
.init(.flexible()), // C seat
.init(.flexible()), // D seat
.init(.flexible()), // E seat
.init(.fixed(40)), // Aisle with row number
.init(.flexible()), // F seat
.init(.flexible()) // G seat
]
var body: some View {
ScrollView([.vertical, .horizontal], showsIndicators: true) {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(seats) { seat in
switch seat.id.letter {
case "A", "B", "C", "D", "E", "F", "G":
SeatView(seat: seat)
.onTapGesture {
toggleSeat(seat: seat)
}
default:
Spacer()
}
if seat.id.letter == "B" || seat.id.letter == "E" {
Text("\(seat.id.row)")
.font(.headline)
.frame(width: 40, height: 40)
}
}
}
.padding()
}
}
func toggleSeat(seat: Seat) {
if let index = seats.firstIndex(of: seat) {
seats[index].state = seats[index].state == .empty ? .occupied : .empty
}
}
}
With SwiftUI, building complex layouts becomes a breeze. Our seat map, with different configurations and aisles, is just a demonstration of how adaptable and flexible SwiftUI grids can be.
Remember, you can further customize the appearance, add more features like zooming, selecting multiple seats, or fetching seat availability from a server. The possibilities are limitless! Happy coding!