ios SwiftUI -添加拖动手势时搜索栏不起作用

m3eecexj  于 2023-08-08  发布在  iOS
关注(0)|答案(2)|浏览(125)

我在主视图的底部有一个标签视图。点击选项卡会打开另一个视图,它是选项卡视图后面的自定义模式(在此示例代码中,它显示为主视图)。无论如何,主要问题是,这个视图有一个搜索栏,每当拖动手势被添加到这个视图,然后搜索栏不工作,即。点击搜索栏不会弹出键盘。
当拖动手势出现时,如何使搜索栏工作?
我的代码太多太复杂了。我添加了一些代码使其成为示例代码。除了在我的实际应用程序中,附加到选项卡的视图是选项卡栏后面的模态,而在这个示例中,它是主视图。但是这个问题在这个示例代码中是可以重现的。

  • 验证码:*
import SwiftUI
import Foundation
import Combine

struct ContentView: View {
    var body: some View {
        VStack {
            SimpleDataView()
        }
        .overlay(alignment: .bottom) {
            BottomTabView()
        }
    }
}

struct SimpleDataView: View {
    var body: some View {
        VStack {
            Text("Map will be displayed over here").background(Color.gray).frame(maxWidth: .infinity, maxHeight: .infinity)
            Spacer()
        }
        .background(Color.gray)
        .ignoresSafeArea()
    }
}

struct BottomTabView: View {
    @State private var defaultHandleColor = Color.secondary
    @State private var activeHandleColor = Color.primary
    @State private var sliderHandleHeight: CGFloat = 15.0
    @State private var radius: CGFloat = 16
    
    /// The latest recorded drag gesture value.
    @State var latestDragGesture: DragGesture.Value?
    @State private var maximumHeight: CGFloat = .infinity
    @State private var isPanelExpanding: Bool = false
    @State private var handleColor = Color.secondary

    
    @State var selection: Int = 1
    var body: some View {
        TabView(selection: $selection) {
            Group {
                ZStack {
                    SearchExploreModalView()
                }.tabItem {
                    Label("Explore", systemImage: "magnifyingglass")
                    Text("Explore")
                }
                .tag(1)
                .gesture(drag)
            }
        }
        .background(Color(red: 0.98, green: 0.98, blue: 0.98).opacity(0.94))
        .onAppear {
            let appearance = UITabBarAppearance()
            UITabBar.appearance().scrollEdgeAppearance = appearance
        }
    }
    
    var drag: some Gesture {
        DragGesture(minimumDistance: 0, coordinateSpace: .global)
            .onChanged {
                let deltaY = $0.location.y - (latestDragGesture?.location.y ?? $0.location.y)
                let proposedHeight = 250.0 + (-1 * deltaY)
                self.isPanelExpanding = proposedHeight >= 250.0 ? true : false
                handleColor = activeHandleColor
                latestDragGesture = $0
            }
            .onEnded { _ in
                // On Ended logic
            }
    }
}

struct SearchExploreModalView: View {
    @State private var searchText = ""
    let searchTextPublisher = PassthroughSubject<String, Never>()

    var body: some View {
        VStack {
            NavigationView {
                List {
                    // For loop iterating overdata
                }
                .searchable(
                    text: $searchText,
                    placement: .navigationBarDrawer(displayMode: .always),
                    prompt: "Search"
                )
                .onChange(of: searchText) { newText in
                    searchTextPublisher.send(newText) /// Publishes when a search term is changed. This is used to debounce the search.
                }
            }
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.gray)
    }
}

字符串

zaq34kh6

zaq34kh61#

我相信在屏幕上不同的手势之间存在一些优先级冲突,这导致了幕后的一些问题。
这可能是一个bug,所以也许将来访问这个问题的人可以参与进来。
我可以通过在.gesture之前的行上添加一个空的onTapGesture来使它工作-见下文:

struct BottomTabView: View {
    @State private var defaultHandleColor = Color.secondary
    @State private var activeHandleColor = Color.primary
    @State private var sliderHandleHeight: CGFloat = 15.0
    @State private var radius: CGFloat = 16
    
    /// The latest recorded drag gesture value.
    @State var latestDragGesture: DragGesture.Value?
    @State private var maximumHeight: CGFloat = .infinity
    @State private var isPanelExpanding: Bool = false
    @State private var handleColor = Color.secondary

    
    @State var selection: Int = 1
    var body: some View {
        TabView(selection: $selection) {
            Group {
                ZStack {
                    SearchExploreModalView()
                }.tabItem {
                    Label("Explore", systemImage: "magnifyingglass")
                    Text("Explore")
                }
                .tag(1)
                .onTapGesture {} // <-- Here!!
                .gesture(drag)
            }
        }
        .background(Color(red: 0.98, green: 0.98, blue: 0.98).opacity(0.94))
        .onAppear {
            let appearance = UITabBarAppearance()
            UITabBar.appearance().scrollEdgeAppearance = appearance
        }
    }
    
    var drag: some Gesture {
        DragGesture(minimumDistance: 0, coordinateSpace: .global)
            .onChanged {
                print("hihihihi")
                let deltaY = $0.location.y - (latestDragGesture?.location.y ?? $0.location.y)
                let proposedHeight = 250.0 + (-1 * deltaY)
                self.isPanelExpanding = proposedHeight >= 250.0 ? true : false
                handleColor = activeHandleColor
                latestDragGesture = $0
            }
            .onEnded { _ in
                // On Ended logic
            }
    }
}

字符串

sqyvllje

sqyvllje2#

这是因为您将手势添加到了NavigationView,其中包含搜索栏。当你点击搜索栏时,SwiftUI会优先考虑你的拖动手势,而不是搜索栏内置的点击手势。
超级视图中的手势行为覆盖子视图中的内置手势似乎是一个常见的问题。参见:1234
解决这个问题的一种方法是简单地不在NavigationView上添加手势。将其添加到List

struct SearchExploreModalView<T: Gesture>: View {
    ...

    let drag: T

    var body: some View {
        VStack {
            NavigationView {
                List {
                    ...
                }
                ...
                .gesture(drag) // <--- here!
            }
            Spacer()
        }
        ...

    }
}

字符串
当然,这使得NavigationView的某些部分(例如工具栏按钮)不能检测手势。你也可以尝试在NavigationView的这些部分添加相同的手势。
或者,将minimumDistance设置得更高,拖动手势才能成功。

DragGesture(minimumDistance: 1, coordinateSpace: .global)


这允许搜索栏的点击手势在您只是点击它时成功。

相关问题