anyone know how to toggle gestures between subviews?
I have a TabView that is made up of 3 pages. Swiping on the page navigates me to another page. In one of the pages, I used Apple's Chart API, that contains a Drag Gesture. Idea is to longPress on the Chart to enable the drag gesture of the chart, else, a swipe on the Chart will use the TabView's drag gesture to slide to next page. But when trying to swipe on the chart, the TabView's swipe gesture isn't recognized. It's only recognized outside of the chart. Any idea on how to disable Chart gestures until longPressed gesture, within my Chart's view, is completed?
I looked into using .allowHitTesting modifier to disable Charts but I wasn't able to toggle it on upon longPressed as all hit detection is disabled. Any ideas?
struct HomePageDetailView: View {
@State var allowHit = false
var body: some View {
TabView {
HomePageChartDetailView()
Color.red
Color.blue
}
.tabViewStyle(.page)
}
}
HomePageChartDetailView
struct HomePageChartDetailView: View {
@State var range: (Date, Date)? = nil
@GestureState var initialdragState = false
@State var enablePriceDrag = false
@State var startItemIndex = 0
@State var currentItemIndex = 0
...
var body: some View {
let longPress = LongPressGesture(minimumDuration: 0.5)
.onEnded { value in
self.enablePriceDrag.toggle()
}
VStack(alignment: .leading) {
Picker("Date Chosen", selection: $selectedTimeLine) {
...
}
Chart(data, id: \.id) { stock in
LineMark(x: .value("Index", stock.formattedDate), y: .value("Value", stock.close))
AreaMark(x: .value("Index", stock.formattedDate), y: .value("Value", stock.close))
if let (start, end) = range, enablePriceDrag {
RectangleMark(xStart: .value("Range", start), xEnd: .value("Range End", end))
.foregroundStyle(.red)
}
}
.chartAxisModifier(value: $enablePriceDrag)
.chartOverlay(content: { proxy in
GeometryReader { g in
Rectangle().fill(.clear).contentShape(Rectangle())
.gesture(
longPress
.sequenced(before: DragGesture(minimumDistance: 0)
.updating($initialdragState, body: { gesture, value, transaction in
})
.onChanged { value in
let startX = value.startLocation.x
let currentX = value.location.x
let endX = g[proxy.plotAreaFrame].width
let xOrigin = g[proxy.plotAreaFrame].origin.x
///Retrieves Each Price Object in Chart
let eachItem = endX / CGFloat(data.count)
let startItemIndex = Int(startX / eachItem)
let tempItemIndex = Int(currentX / eachItem)
self.startItemIndex = startItemIndex
currentItemIndex = tempItemIndex
///Find the date values at the x coordinates.
if let startDate: Date = proxy.value(atX: startX),
let currentDate: Date = proxy.value(atX: currentX),
let endDate: Date = proxy.value(atX: endX),
let originDate: Date = proxy.value(atX: xOrigin),
startDate < endDate && currentDate < endDate,
currentDate > originDate {
range = (startDate, currentDate)
}
}
.onEnded { _ in
enablePriceDrag = false
range = nil
}))
}
})
}
}
Image for reference: