在 SwiftUI 中更改选定的单元格背景颜色

问题描述

我编写了以下代码并带来了这种输出

output

通过使用 .onTapGesture 方法,我从 HStack 中找到所选日期

但我想根据 Hstack 中的单元格选择更改背景颜色。

任何人都可以为更改 HStack 上选定的单元格背景颜色提供一些想法或建议。

或者与我分享任何参考资料。

struct CalendarDay: Identifiable {
                let id = UUID()
                var number: String
                var weekday: String
                var isToday: Bool
            }
            struct ContentView: View {
                @State var days = [CalendarDay]()
                
                var body: some View {
                    ZStack{
                        vstack {
                            
                            //MARK: CALENDAR
                            ScrollView(.horizontal,showsIndicators: false){
                                HStack(spacing: 20) {
                                    
                                    ForEach(days) { day in
                                        CalendarView(
                                            number: day.number,days: day.weekday,color: day.isToday ? #colorLiteral(red: 0.9060331583,green: 0.2547450066,blue: 0.3359550834,alpha: 1) : #colorLiteral(red: 1,green: 1,blue: 1,alpha: 1),textcolor: day.isToday ? #colorLiteral(red: 1,alpha: 1) : #colorLiteral(red: 0,green: 0,blue: 0,alpha: 1)
                                        )
    .onTapGesture{
    print(day)
    }
                                    }
                                }
                                .padding(.leading,10)
                                .padding(.bottom,10)
                                .shadow(radius: 3,x: 3,y: 3)
                            }
                            
                        }
                    }
                    .onAppear {
                        getCurrentWeekdays()
                    }
                }
                
                func getCurrentWeekdays() {
                    /// from https://stackoverflow.com/a/62355272/14351818
                    let dateComponents = Calendar(identifier: .gregorian).dateComponents([.yearForWeekOfYear,.weekOfYear],from: Date())
                    let startOfWeek = Calendar(identifier: .gregorian).date(from: dateComponents)!
                    let startOfWeekNoon = Calendar(identifier: .gregorian).date(bySettingHour: 12,minute: 0,second: 0,of: startOfWeek)!
                    
                    days = (0...6).map {
                        let calendar = Calendar(identifier: .gregorian)
                        let date = calendar.date(byAdding: .day,value: $0,to: startOfWeekNoon)!
                        
                        let numberDateFormatter = DateFormatter()
                        numberDateFormatter.dateFormat = "d"
                        let number = numberDateFormatter.string(from: date)
                        
                        let weekdayDateFormatter = DateFormatter()
                        weekdayDateFormatter.dateFormat = "E"
                        let weekday = weekdayDateFormatter.string(from: date)
                        
                        let calendarDay = CalendarDay(
                            number: number,weekday: weekday,isToday: calendar.component(.day,from: Date()) == calendar.component(.day,from: date)
                        )
                        
                        return calendarDay
                    }
                    
                }
            }
            
            struct CalendarView: View {
                var number : String
                var days : String
                var color : UIColor
                var textcolor : UIColor
                
                var body: some View {
                    vstack{
                        Text(self.number)
                            .font(.system(size: 20,weight: .bold,design: .rounded))
                            .foregroundColor(Color(self.textcolor))
                        Text(self.days)
                            .font(.headline)
                            .foregroundColor(Color(self.textcolor))
                    }.padding([.top,.bottom],10)
                    .padding([.leading,.trailing],10)
                    .background(Color(self.color))
                    .cornerRadius(30)
                }
            }

解决方法

尝试这样的事情:

import SwiftUI

struct CalendarDay: Identifiable {
    let id = UUID()
    var number: String
    var weekday: String
    var isToday: Bool
}

struct ContentView: View {
    @State var days = [CalendarDay]()
    
    var body: some View {
        ZStack{
            VStack {
                ScrollView(.horizontal,showsIndicators: false){
                    HStack(spacing: 20) {
                        
                    //  <--- 
                    ForEach(days.indices,id: \.self) { i in
                        CalendarView(
                            number: days[i].number,days: days[i].weekday,color: days[i].isToday ? #colorLiteral(red: 0.9060331583,green: 0.2547450066,blue: 0.3359550834,alpha: 1) : #colorLiteral(red: 1,green: 1,blue: 1,alpha: 1),textcolor: days[i].isToday ? #colorLiteral(red: 1,alpha: 1) : #colorLiteral(red: 0,green: 0,blue: 0,alpha: 1)
                        )
                            .onTapGesture{
                                print(days[i])
                                // this is just for replacing the current selection
                                for j in days.indices { days[j].isToday = false }
                                days[i].isToday = true
                            }
                    }
                  //  <---

                    }
                    .padding(.leading,10)
                    .padding(.bottom,10)
                    .shadow(radius: 3,x: 3,y: 3)
                }
                
            }
        }
        .onAppear {
            getCurrentWeekdays()
        }
    }
    
    func getCurrentWeekdays() {
        /// from https://stackoverflow.com/a/62355272/14351818
        let dateComponents = Calendar(identifier: .gregorian).dateComponents([.yearForWeekOfYear,.weekOfYear],from: Date())
        let startOfWeek = Calendar(identifier: .gregorian).date(from: dateComponents)!
        let startOfWeekNoon = Calendar(identifier: .gregorian).date(bySettingHour: 12,minute: 0,second: 0,of: startOfWeek)!
        
        days = (0...6).map {
            let calendar = Calendar(identifier: .gregorian)
            let date = calendar.date(byAdding: .day,value: $0,to: startOfWeekNoon)!
            
            let numberDateFormatter = DateFormatter()
            numberDateFormatter.dateFormat = "d"
            let number = numberDateFormatter.string(from: date)
            
            let weekdayDateFormatter = DateFormatter()
            weekdayDateFormatter.dateFormat = "E"
            let weekday = weekdayDateFormatter.string(from: date)
            
            let calendarDay = CalendarDay(
                number: number,weekday: weekday,isToday: calendar.component(.day,from: Date()) == calendar.component(.day,from: date)
            )
            
            return calendarDay
        }
        
    }
}

struct CalendarView: View {
    var number : String
    var days : String
    var color : UIColor
    var textcolor : UIColor
    
    var body: some View {
        VStack{
            Text(self.number)
                .font(.system(size: 20,weight: .bold,design: .rounded))
                .foregroundColor(Color(self.textcolor))
            Text(self.days)
                .font(.headline)
                .foregroundColor(Color(self.textcolor))
        }.padding([.top,.bottom],10)
            .padding([.leading,.trailing],10)
            .background(Color(self.color))
            .cornerRadius(30)
    }
}