SwiftUI在存在覆盖层时无法检测滑动。

huangapple go评论59阅读模式
英文:

SwiftUI doesn’t detect swipe when there is an overlay

问题

import SwiftUI

struct ContentView: View {
    
    @State private var isLoading = false
    
    var body: some View {
        VStack {
            GeometryReader { proxy in
                Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere.\n \t Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere.")
                    .padding()
                    .frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
            }
        }
        .gesture(DragGesture(minimumDistance: 1.0, coordinateSpace: .global)
            .onEnded ({ value in
                if value.translation.height < 0 {
                    isLoading = true
                } else {
                    isLoading = false
                }
                print(isLoading)
            }))
        .overlay(alignment: .bottom){
            loadingOverlay
        }
    }
    @ViewBuilder private var loadingOverlay: some View{
        if(isLoading){
            SlidingView()
                .transition(.asymmetric(insertion: .move(edge: .bottom), removal: .opacity))
                .animation(.easeInOut(duration: 0.3))
        }
    }
}
struct SlidingView: View{
    
    @State private var up = false
    
    var body: some View{
        
        GeometryReader{ proxy in
            VStack(spacing: 20){
                Image(systemName: up ? "chevron.compact.up" : "chevron.compact.down")
                    .resizable()
                    .scaledToFit()
                    .frame(width: 40, height: 40)
                    .foregroundColor(.black)
                Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere.")
                    .padding()
                Spacer()
            }
            .frame(width: proxy.size.width, height: 1000)
            .background(Color(.lightGray))
            .cornerRadius(30)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
英文:

I'm trying to create an app with an overlay that activates when there is an upwards swipe and goes away with a downward swipe. Most of the program functions normally but when I swipe with the overlay showing it can't recognize swipes in any direction. If the overlay isn't being displayed the program recognizes swipes just fine.

import SwiftUI
struct ContentView: View {
@State private var isLoading = false
var body: some View {
VStack {
GeometryReader{ proxy in
Text(&quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod          tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere.\n \t Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere. &quot;)
.padding()
.frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
}
}
.gesture(DragGesture(minimumDistance: 1.0, coordinateSpace: .global)
.onEnded ({ value in
if value.translation.height &lt; 0 {
isLoading = true
}else{
isLoading = false
}
print(isLoading)
}))
.overlay(alignment: .bottom){
loadingOverlay
}
}
@ViewBuilder private var loadingOverlay: some View{
if(isLoading){
SlidingView()
.transition(.asymmetric(insertion: .move(edge: .bottom), removal: .opacity))
.animation(.easeInOut(duration: 0.3))
}
}
}
struct SlidingView: View{
@State private var up = false
var body: some View{
GeometryReader{ proxy in
VStack(spacing: 20){
Image(systemName: up ? &quot;chevron.compact.up&quot; : &quot;chevron.compact.down&quot;)
.resizable()
.scaledToFit()
.frame(width: 40, height: 40)
.foregroundColor(.black)
Text(&quot;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Tortor consequat id porta nibh venenatis cras. Pharetra vel turpis nunc eget lorem dolor sed. Ultrices tincidunt arcu non sodales. Sem nulla pharetra diam sit amet nisl suscipit. Vitae aliquet nec ullamcorper sit. Sed felis eget velit aliquet sagittis. Feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Condimentum mattis pellentesque id nibh. Sit amet est placerat in egestas erat imperdiet sed. Diam donec adipiscing tristique risus nec feugiat in fermentum posuere.&quot;)
.padding()
Spacer()
}
.frame(width: proxy.size.width, height: 1000)
.background(Color(.lightGray))
.cornerRadius(30)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

答案1

得分: 0

以下是翻译好的部分:

  1. .allowsHitTesting(false) 应用于覆盖层:
        .overlay(alignment: .bottom) {
            loadingOverlay
                .allowsHitTesting(false)
        }
  1. 或者,也可以将拖拽手势添加到覆盖层中。您可以通过将其移动到计算属性中来重复使用相同的手势。与此同时,您可以使用 withAnimation 代替已弃用的动画修饰符以避免警告:
    var dragged: some Gesture {
        DragGesture(minimumDistance: 1.0, coordinateSpace: .global)
            .onEnded { value in
                withAnimation {
                    isLoading = value.translation.height &lt; 0
                }
                print(isLoading)
            }
    }

    var body: some View {
        VStack {
            // 与之前一样的内容
        }
        .gesture(dragged)
        .overlay(alignment: .bottom) {
            loadingOverlay
                .gesture(dragged)
        }
    }

    @ViewBuilder private var loadingOverlay: some View {
        if isLoading {
            SlidingView()
                .transition(.asymmetric(insertion: .move(edge: .bottom), removal: .opacity))
        }
    }

英文:

Here are two ways to fix:

  1. Apply .allowsHitTesting(false) to the overlay:
        .overlay(alignment: .bottom) {
            loadingOverlay
                .allowsHitTesting(false)
        }
  1. Alternatively, add the drag gesture to the overlay too. You can re-use the same gesture by moving it to a computed property. While you're at it, you could avoid the warning for the deprecated animation modifier by using withAnimation instead:
    var dragged: some Gesture {
        DragGesture(minimumDistance: 1.0, coordinateSpace: .global)
            .onEnded { value in
                withAnimation {
                    isLoading = value.translation.height &lt; 0
                }
                print(isLoading)
            }
    }

    var body: some View {
        VStack {
            // Content as before
        }
        .gesture(dragged)
        .overlay(alignment: .bottom) {
            loadingOverlay
                .gesture(dragged)
        }
    }

    @ViewBuilder private var loadingOverlay: some View {
        if isLoading {
            SlidingView()
                .transition(.asymmetric(insertion: .move(edge: .bottom), removal: .opacity))
        }
    }

huangapple
  • 本文由 发表于 2023年7月14日 04:19:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682984.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定