ios SwiftUI -滚动时关闭键盘

2w3kk1z5  于 2023-06-07  发布在  iOS
关注(0)|答案(6)|浏览(262)

我有一个简单的搜索列表:

struct ContentView: View {
    @State var text:String = ""
    var items = 1...100
    var body: some View {
        VStack {
            List {
                TextField("Search", text: $text)
                Section{
                    ForEach(items.filter({"\($0)".contains(text)}),id: \.self){(i) in
                       Text("option \(i)")
                    }
                }
            }
        }
    }
}

如何在滚动超过2个单元格/几个点时关闭键盘?

wbgh16ku

wbgh16ku1#

如果你使用的是ScrollView(可能也有List,但我还没有确认),你可以使用UIScrollViewappearance,这将影响所有的ScrollViews。

UIScrollView.appearance().keyboardDismissMode = .onDrag
mi7gmzs6

mi7gmzs62#

对于this question,可以找到关于如何重新分配键盘的各种答案的详细讨论。
在列表中的拖动手势上重命名键盘的一个解决方案是使用UIApplication窗口上的方法,如下所示。为了更容易处理,我在UIApplication上创建了一个扩展,并为此扩展创建了视图修改器,最后是View的扩展:

extension UIApplication {
    func endEditing(_ force: Bool) {
        self.windows
            .filter{$0.isKeyWindow}
            .first?
            .endEditing(force)
    }
}

struct ResignKeyboardOnDragGesture: ViewModifier {
    var gesture = DragGesture().onChanged{_ in
        UIApplication.shared.endEditing(true)
    }
    func body(content: Content) -> some View {
        content.gesture(gesture)
    }
}

extension View {
    func resignKeyboardOnDragGesture() -> some View {
        return modifier(ResignKeyboardOnDragGesture())
    }
}

因此,最后一个用于重新指定键盘的修饰符只是一个修饰符,必须像这样放置在列表中:

List {
    ForEach(...) {
        //...
    }
}
.resignKeyboardOnDragGesture()

我还实现了一个纯swiftUI版本的搜索栏,您可能会感兴趣。你可以在这个答案中找到它。

v6ylcynt

v6ylcynt3#

至于现在,自iOS 16 beta以来,我们有一个新的修改器scrollDismissesKeyboard(),它允许做你需要的事情。
在您的示例中,它应该看起来像

struct ContentView: View {
    @State var text: String = ""
    var items = 1...100
    var body: some View {
        List {
            TextField("Search", text: $text)
            Section {
                ForEach(items.filter({"\($0)".contains(text)}), id: \.self) { (i) in
                    Text("option \(i)")
                }
            }
        }
        .scrollDismissesKeyboard(.interactively) // <<-- Put this line
    }
}

scrollDismissesKeyboard()修饰符有一个确定解除规则的参数。以下是可能的值:

  • .automatic:根据滚动的上下文解除。
  • .immediately:一旦发生任何滚动,键盘将被关闭。
  • .interactively:键盘将随着用户的手势移动/消失。
  • .never:当用户滚动时,键盘永远不会消失。
s2j5cfk0

s2j5cfk04#

Form {
    ...
}.gesture(DragGesture().onChanged { _ in
    UIApplication.shared.windows.forEach { $0.endEditing(false) }
})
wecizke3

wecizke35#

@FocusState wrapper沿着.focused()TextField modifier可能很有用。

struct ContentView: View {
    @FocusState private var focusedSearchField: Bool
    @State var text:String = ""
    var items = 1...100
    var body: some View {
        VStack {
            List {
                TextField("Search", text: $text)
                    .focused($focusedSearchField)
                Section{
                    ForEach(items.filter({"\($0)".contains(text)}),id: \.self){(i) in
                        Text("option \(i)")
                    }
                }
            } // to also allow swipes on items (theoretically)
            .simultaneousGesture(DragGesture().onChanged({ _ in
                focusedSearchField = false
            }))
            .onTapGesture { // dissmis on tap as well
                focusedSearchField = false
            }
        }
    }
}
pvabu6sv

pvabu6sv6#

struct EndEditingKeyboardOnDragGesture: ViewModifier {
    func body(content: Content) -> some View {
        content.highPriorityGesture (
            DragGesture().onChanged { _ in 
                UIApplication.shared.endEditing()
            }
        )
    }
}

extension View {
    func endEditingKeyboardOnDragGesture() -> some View {
        return modifier(EndEditingKeyboardOnDragGesture())
    }
}

相关问题