如何检测swiftui中是否存在键盘

dar*_*n z 1 swift swiftui

我想知道按下按钮时键盘是否存在。我该怎么做?我试过了,但我没有任何运气。谢谢。

Max*_*Max 27

我的一点改进@George的回答。

在 View 协议中实现发布者

import Combine
extension View {
  var keyboardPublisher: AnyPublisher<Bool, Never> {
    Publishers
      .Merge(
        NotificationCenter
          .default
          .publisher(for: UIResponder.keyboardWillShowNotification)
          .map { _ in true },
        NotificationCenter
          .default
          .publisher(for: UIResponder.keyboardWillHideNotification)
          .map { _ in false })
      .debounce(for: .seconds(0.1), scheduler: RunLoop.main)
      .eraseToAnyPublisher()
  }
}
Run Code Online (Sandbox Code Playgroud)

我还添加了去抖动运算符,以便当您有多个文本字段并且用户在它们之间移动时防止 true - false 切换。

在任何视图中使用

struct SwiftUIView: View {
  @State var isKeyboardPresented = false
  @State var firstTextField = ""
  @State var secondTextField = ""
  
  var body: some View {
    VStack {
      TextField("First textField", text: $firstTextField)
      TextField("Second textField", text: $secondTextField)
    }
    .onReceive(keyboardPublisher) { value in
      isKeyboardPresented = value
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 等等,什么,制表符缩进设置为 2?你去麦克斯,坚持住他们!(自八十年代以来,我拒绝将选项卡设置为除 2 之外的任何选项:-) (4认同)

Eil*_*lon 15

iOS 15:

您可以使用focused(_:)视图修饰符和@FocusState属性包装器来了解文本字段是否正在编辑,还可以更改编辑状态。

@State private var text: String = ""
@FocusState private var isTextFieldFocused: Bool

var body: some View {
    VStack {
        TextField("hello", text: $text)
            .focused($isTextFieldFocused)
        
        if isTextFieldFocused {
            Button("Keyboard is up!") {
                isTextFieldFocused = false
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 焦点和键盘存在不一定是同一件事。如果连接了外部键盘,则就键盘存在而言,这将不会显示正确的结果。 (26认同)

Con*_*lon 12

有了环境钥匙...

采用@Lepidopteron 的答案,但用它来驱动环境密钥。

这允许您在任何视图中使用访问键盘状态

@Environment(\.keyboardShowing) var keyboardShowing
Run Code Online (Sandbox Code Playgroud)

您所要做的就是在层次结构的顶部添加一个视图修饰符

RootView()
.addKeyboardVisibilityToEnvironment()
Run Code Online (Sandbox Code Playgroud)

这全部由以下 ViewModifier 文件提供支持...

public extension View {
    
    /// Sets an environment value for keyboardShowing
    /// Access this in any child view with
    /// @Environment(\.keyboardShowing) var keyboardShowing
    func addKeyboardVisibilityToEnvironment() -> some View {
        modifier(KeyboardVisibility())
    }
}

private struct KeyboardShowingEnvironmentKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

extension EnvironmentValues {
    var keyboardShowing: Bool {
        get { self[KeyboardShowingEnvironmentKey.self] }
        set { self[KeyboardShowingEnvironmentKey.self] = newValue }
    }
}

private struct KeyboardVisibility:ViewModifier {
    
#if os(macOS)
    
    fileprivate func body(content: Content) -> some View {
        content
            .environment(\.keyboardShowing, false)
    }
    
#else
    
    @State var isKeyboardShowing:Bool = false
    
    private var keyboardPublisher: AnyPublisher<Bool, Never> {
        Publishers
            .Merge(
                NotificationCenter
                    .default
                    .publisher(for: UIResponder.keyboardWillShowNotification)
                    .map { _ in true },
                NotificationCenter
                    .default
                    .publisher(for: UIResponder.keyboardWillHideNotification)
                    .map { _ in false })
            .debounce(for: .seconds(0.1), scheduler: RunLoop.main)
            .eraseToAnyPublisher()
    }
    
    fileprivate func body(content: Content) -> some View {
        content
            .environment(\.keyboardShowing, isKeyboardShowing)
            .onReceive(keyboardPublisher) { value in
                isKeyboardShowing = value
            }
    }
    
#endif
}
Run Code Online (Sandbox Code Playgroud)


Geo*_*e_E 5

使用此协议,KeyboardReadable您可以遵循任何协议View并从中获取键盘更新。

KeyboardReadable 协议:

import Combine
import UIKit


/// Publisher to read keyboard changes.
protocol KeyboardReadable {
    var keyboardPublisher: AnyPublisher<Bool, Never> { get }
}

extension KeyboardReadable {
    var keyboardPublisher: AnyPublisher<Bool, Never> {
        Publishers.Merge(
            NotificationCenter.default
                .publisher(for: UIResponder.keyboardWillShowNotification)
                .map { _ in true },
            
            NotificationCenter.default
                .publisher(for: UIResponder.keyboardWillHideNotification)
                .map { _ in false }
        )
        .eraseToAnyPublisher()
    }
}
Run Code Online (Sandbox Code Playgroud)

它的工作原理是使用 Combine 并创建一个发布者,以便我们可以接收键盘通知。

通过如何应用它的示例视图:

struct ContentView: View, KeyboardReadable {
    
    @State private var text: String = ""
    @State private var isKeyboardVisible = false
    
    var body: some View {
        TextField("Text", text: $text)
            .onReceive(keyboardPublisher) { newIsKeyboardVisible in
                print("Is keyboard visible? ", newIsKeyboardVisible)
                isKeyboardVisible = newIsKeyboardVisible
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以从isKeyboardVisible变量中读取以了解键盘是否可见。

TextField显示键盘处于活动状态时,将打印以下内容:

键盘是否可见?真的

当键盘在按回车键时隐藏时,将打印以下内容:

键盘是否可见?错误的

您可以在键盘开始出现或消失时使用keyboardWillShowNotification/keyboardWillHideNotification进行更新,并在键盘出现或消失后使用keyboardDidShowNotification/keyboardDidHideNotification变体进行更新。我更喜欢这个will变体,因为当键盘显示时更新是即时的。