在 WebView 中检测滚动和点击会阻止 SwiftUI 中的滚动
Detect Scroll and Tap in WebView blocks the scroll in SwiftUI
我在 SwiftUI 中有一个 WebView
和 UIViewRepresentable
,我想获取触摸和滑动(滚动)的坐标。但问题是,如果我尝试获取坐标,WebView
中的网站将禁用滚动,就像阻止 UIKit Wrapper 的手势一样。这种行为背后发生了什么,解决它的方法是什么?因为否则代码工作完美。
SwiftUI
代码:
struct TaskSwipeGesture: View {
let urlWeb: String = "https://www.google.com/?client=safari"
var body: some View {
WebView(url: urlWeb)
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
print("Change: X Coordinate is: \(value.location.x), Y Coordinate is: \(value.location.y)")
})
.onEnded({ value in
print("Ended: X Coordinate is: \(value.location.x), Y Coordinate is: \(value.location.y)")
})
)
}
}
WebView
包装器:
struct WebView: UIViewRepresentable {
let url: String
func makeUIView(context: Context) -> some WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: UIViewType, context: Context) {
let request = URLRequest(url: URL(string: url)!)
uiView.load(request)
}
}
您可以使用 webView.scrollView.delegate
以 UIKit 方式处理事件
首先你需要创建ScrollViewDelegate
class MyScrollViewDelegate: NSObject {
weak var webView: WKWebView?
}
extension MyScrollViewDelegate: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
printLocation(for: scrollView, label: "will begin dragging")
}
func scrollViewWillEndDragging(
_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>)
{
printLocation(for: scrollView, label: "will end dragging")
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.isTracking {
printLocation(for: scrollView, label: "is tracking")
}
}
private func printLocation(for scrollView: UIScrollView, label: String) {
if let webView = webView {
print("\(label) \(scrollView.panGestureRecognizer.location(in: webView))")
}
}
}
然后将其应用到您的 WebView
包装器中
struct WebView: UIViewRepresentable {
let url: String
let scrollViewDelegate = MyScrollViewDelegate()
func makeUIView(context: Context) -> some WKWebView {
let webView = WKWebView()
scrollViewDelegate.webView = webView
webView.scrollView.delegate = scrollViewDelegate
return webView
}
func updateUIView(_ uiView: UIViewType, context: Context) {
let request = URLRequest(url: URL(string: url)!)
uiView.load(request)
}
}
之后,ContentView
会变成这样
struct TaskSwipeGesture: View {
let urlWeb: String = "https://www.google.com/?client=safari"
var body: some View {
WebView(url: urlWeb)
}
}
我在 SwiftUI 中有一个 WebView
和 UIViewRepresentable
,我想获取触摸和滑动(滚动)的坐标。但问题是,如果我尝试获取坐标,WebView
中的网站将禁用滚动,就像阻止 UIKit Wrapper 的手势一样。这种行为背后发生了什么,解决它的方法是什么?因为否则代码工作完美。
SwiftUI
代码:
struct TaskSwipeGesture: View {
let urlWeb: String = "https://www.google.com/?client=safari"
var body: some View {
WebView(url: urlWeb)
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged({ value in
print("Change: X Coordinate is: \(value.location.x), Y Coordinate is: \(value.location.y)")
})
.onEnded({ value in
print("Ended: X Coordinate is: \(value.location.x), Y Coordinate is: \(value.location.y)")
})
)
}
}
WebView
包装器:
struct WebView: UIViewRepresentable {
let url: String
func makeUIView(context: Context) -> some WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: UIViewType, context: Context) {
let request = URLRequest(url: URL(string: url)!)
uiView.load(request)
}
}
您可以使用 webView.scrollView.delegate
首先你需要创建ScrollViewDelegate
class MyScrollViewDelegate: NSObject {
weak var webView: WKWebView?
}
extension MyScrollViewDelegate: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
printLocation(for: scrollView, label: "will begin dragging")
}
func scrollViewWillEndDragging(
_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>)
{
printLocation(for: scrollView, label: "will end dragging")
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.isTracking {
printLocation(for: scrollView, label: "is tracking")
}
}
private func printLocation(for scrollView: UIScrollView, label: String) {
if let webView = webView {
print("\(label) \(scrollView.panGestureRecognizer.location(in: webView))")
}
}
}
然后将其应用到您的 WebView
包装器中
struct WebView: UIViewRepresentable {
let url: String
let scrollViewDelegate = MyScrollViewDelegate()
func makeUIView(context: Context) -> some WKWebView {
let webView = WKWebView()
scrollViewDelegate.webView = webView
webView.scrollView.delegate = scrollViewDelegate
return webView
}
func updateUIView(_ uiView: UIViewType, context: Context) {
let request = URLRequest(url: URL(string: url)!)
uiView.load(request)
}
}
之后,ContentView
会变成这样
struct TaskSwipeGesture: View {
let urlWeb: String = "https://www.google.com/?client=safari"
var body: some View {
WebView(url: urlWeb)
}
}