I am trying to create a calendar view that allows users to select multiple date ranges, including non continuous, continuous, and single dates. I also want to allow users to drag to select date ranges but I am struggling to implement that portion.
I believe the issue is my if statement in the dragSelect function, the original from this thread is commented out below it. I’ve tried using DispatchQueue to see if async timing was the problem but I might have done that wrong, it also seems like rectangles.content[i] = gp.frame(in: .named("container"))
could be the problem?. getBackground just sets the background to a certain color if it is contained in the selectedDates set. Any advice is greatly appreciated!!
struct testDrag: View
{
var rectangles = Rectangles()
@State var selectRect: CGRect?
let days = Date.now.calendarDisplayDays
@State private var date = Date.now
private var textColor: Color = .black
private var selectColor: Color = .baseTeal
let daysOfWeek = Date.capitalizedFirstLettersOfWeekdays
let columns = Array(repeating: GridItem(.flexible()), count: 7)
@State private var selectedDates: Set<Date> = []
@State private var selectedCell: CGRect?
var body: some View
{
GeometryReader { geometry in
ZStack(alignment: .topLeading) {
LazyVGrid(columns: columns
,content: {
ForEach(0..<days.count, id: .self) { i in
if days[i].monthInt != date.monthInt {
Text("")
.frame(maxWidth: geometry.size.width/7, minHeight: 40, alignment: .center)
} else {
Text(days[i].formatted(.dateTime.day()))
.fontWeight(.medium)
.frame(minWidth: (geometry.size.width/7) - 3, minHeight: 40, alignment: .center)
.background(getBackground(for: days[i]))
.background() {
GeometryReader { gp -> Color in
rectangles.content[i] = gp.frame(in: .named("container"))
return Color.clear
}
}
.cornerRadius(20)
.onTapGesture {
if selectedDates.contains(days[i].startOfDay) {
selectedDates.remove(days[i].startOfDay)
}
else {
selectedDates.insert(days[i].startOfDay)
}
}
.foregroundColor(
selectedDates.contains(days[i].startOfDay) ? textColor :
(Date.now.startOfDay == days[i].startOfDay ? selectColor : textColor)
)
}
}
})
.coordinateSpace(name: "container")
.gesture(dragSelect)
if let selR = selectRect {
Rectangle()
.frame(width: selR.width, height: selR.height)
.offset(x: selR.origin.x, y: selR.origin.y)
}
}
}
}
private var dragSelect: some Gesture
{
DragGesture(minimumDistance: 2)
.onChanged { drag in
let a = drag.startLocation
let b = drag.location
self.selectRect = CGRect(x: min(a.x, b.x), y: min(a.y, b.y), width: abs(a.x - b.x), height: abs(a.y - b.y))
var resSet = Set<Date>()
for i in 0 ..< self.days.count {
if let rect = self.rectangles.content[i], ((self.selectRect?.intersects(rect)) != nil) {
// if CGRectIntersectsRect(rectangles.content[i]!, selectRect!) {
resSet.insert(days[i])
}
self.selectedDates = resSet
}
}
.onEnded { _ in
self.selectRect = nil
}
}
}
class Rectangles
{
var content = [Int : CGRect]()
}
machigai is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.