【问题标题】:SwiftUI - Close Keyboard on ScrollSwiftUI - 在滚动时关闭键盘
【发布时间】:2020-02-20 18:11:39
【问题描述】:

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


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 个单元格/几个点时如何关闭键盘?

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    @FocusState 包装器和 .focused() TextField 修饰符可能很有用。

    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
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:
      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())
          }
      }
      

      【讨论】:

      • 很遗憾,它会干扰滑动手势。
      【解决方案3】:

      如果您使用ScrollView(可能也使用List,但我还没有确认),您可以使用UIScrollViewappearance,但这会影响所有滚动视图。

      UIScrollView.appearance().keyboardDismissMode = .onDrag
      

      【讨论】:

      • 这是迄今为止最好的建议。也适用于其他视图/组件,例如同一滚动视图上的Slider
      • 这适用于List,正如我测试的那样,可能还有其他可滚动的视图。我猜是因为ListScrollView 的子类
      • 我发现如果显示表情符号键盘并且您滑动表情符号,这会导致键盘奇怪地隐藏 - 关于如何解决此问题的任何想法?
      【解决方案4】:
      Form {
          ...
      }.gesture(DragGesture().onChanged { _ in
          UIApplication.shared.windows.forEach { $0.endEditing(false) }
      })
      

      【讨论】:

      • 不幸的是,我发现这会干扰滑动删除。
      • 还有Slider 组件
      【解决方案5】:

      可以在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 版本的搜索栏,您可能会感兴趣。你可以在this answer找到它。

      【讨论】:

      • 我不知道这是否仍然受到积极监控,但对于 iOS 15,我收到了一条警告,上面写着 'windows' was deprecated in iOS 15.0: Use UIWindowScene.windows on a relevant window scene instead。为 iOS 15 添加代码部分会很有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 2020-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多