[英]SwiftUI ScrollView gesture recogniser
如何檢測何時拖動 ScrollView?
在我的 ScrollView 中,我有一個@Binding scrollPositionOffset
變量,我使用.onChange(of:)
觀看,然后使用ScrollViewReader.scrollTo()
以編程方式滾動到 position 。 這很好用,但是當我直接滾動 ScrollView 時,我還需要更新scrollPositionOffset
。 我正在努力做到這一點,因為這會觸發.onChange(of:)
閉包並進入循環。
我的解決方案是僅在我將localScrolling
變量設置為 false 時有條件地調用ScrollViewReader.scrollTo()
。 我嘗試使用DragGesture.onChanged
和.onEnded
進行設置,但這與導致滾動的拖動手勢不同,因此.onEnded
永遠不會觸發。
我認為我需要的是一個類似於 UIScrollView 的isDragging
或isTracking
的 ScrollView 的 @GestureRecognizer(我知道我可以使用 UIScrollView,但我不知道怎么做,而且這似乎可能更有效!!我會接受一個向我展示如何將其放入 SwiftUIView 的答案)
上下文(如果有人對我的實際情況有更清潔的解決方案):
我有一個 ScrollView,我正在以編程方式滾動以創建類似於 Xcode 中的 Minimap 視圖的效果(即,我有一個與 ScrollView 相鄰的縮小視圖,並且拖動 minimap 會導致 ScrollView 滾動)。
這在我使用小地圖時效果很好,但我正在努力讓相反的事情發生:移動 ScrollView 的 position 以更新小地圖視圖。
代碼
@Binding var scrollPositionOffset: CGFloat
let zoomMultiplier:CGFloat = 1.5
var body: some View{
ScrollViewReader { scrollViewProxy in
GeometryReader{ geometry in
ScrollView {
ZStack(alignment:.top){
//The content of my ScrollView
MagnifierView()
.frame(height: geometry.size.height * zoomMultiplier)
//I'm using this as my offset reference
Rectangle()
.frame(height:10)
.alignmentGuide(.top) { _ in
geometry.size.height * zoomMultiplier * -scrollPositionOffset
}
.id("scrollOffset")
}
}
.onAppear(){
scrollViewProxy.scrollTo("scrollOffset", anchor: .top)
}
.onChange(of: scrollPositionOffset, perform: { _ in
//Only call .scrollTo() if the view isn't already being scrolled by the user
if !localScrolling {
scrollViewProxy.scrollTo("scrollOffset", anchor: .top)
}
})
.gesture(
DragGesture()
.onChanged{gesture in
localScrolling = true
let offset = gesture.location.y/(zoomMultiplier * geometry.size.height)
scrollPositionOffset = offset
}
.onEnded({gesture in
//Doesn't ever fire when scrolling
localScrolling = false
})
)
}
}
}
使用ScrollViewStyle
:
struct CustomScrollView: ScrollViewStyle {
@Binding var isDragging: Bool
func make(body: AnyView, context: Context) -> some View {
body
}
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
class Coordinator: ScrollViewCoordinator {
var parent: CustomScrollView
init(parent: CustomScrollView) {
self.parent = parent
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
parent.isDragging = false
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
parent.isDragging = true
}
}
}
struct TestView: View {
@State var isDragging = false
var body: some View {
ScrollView {
}.scrollViewStyle(CustomScrollView(isDragging: $isDragging))
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.