SwiftUI添加拖拽手势后搜索栏无法唤起键盘的解决方法
问题:拖拽手势导致搜索栏无法唤起键盘
主视图底部通过Overlay添加了TabView,点击标签页会打开后方的自定义模态视图(示例中为SearchExploreModalView)。但为标签项添加拖拽手势后,视图内的搜索栏点击无法唤起键盘。
复现代码
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) } }
解决方案
问题根源
设置minimumDistance: 0的DragGesture会捕获所有触摸事件,包括搜索栏的点击操作,导致搜索栏无法接收到点击信号,无法唤起键盘。
修复方法:调整拖拽手势的最小触发距离
将DragGesture的minimumDistance从0改为一个较小的正值(比如5),这样只有当用户的触摸移动超过这个距离时才会触发拖拽手势,点击事件会正常传递给搜索栏。
修改后的拖拽手势代码:
var drag: some Gesture { DragGesture(minimumDistance: 5, coordinateSpace: .global) // 修改minimumDistance .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 } }
替代方案:使用手势优先级控制
如果需要保留minimumDistance: 0,可以通过highPriorityGesture确保搜索栏的交互优先:
// 在SearchExploreModalView的NavigationView上添加高优先级点击手势 NavigationView { List { // For loop iterating overdata } .searchable( text: $searchText, placement: .navigationBarDrawer(displayMode: .always), prompt: "Search" ) .onChange(of: searchText) { newText in searchTextPublisher.send(newText) } } .highPriorityGesture(TapGesture().onEnded { // 空实现,确保点击事件被搜索栏接收 })
不过这种方法不如调整minimumDistance简洁有效,推荐优先使用第一种方案。
内容的提问来源于stack exchange,提问作者tech_human
相关产品推荐
相关产品推荐

