SwiftUI中如何让TextField始终在键盘顶部?

4
我有这个。
struct ContentView: View {
    var body: some View {
        ZStack(alignment: Alignment.bottom) {
            List {
                Text("Default text").foregroundColor(Color.red)
            }
            TextField("Placeholder", text: .constant(""))
                .frame(minHeight: 30)
                .cornerRadius(8.0)
                .padding(10)
                .background(Color.blue)
        }
    }
}

实际上,当我聚焦于文本框时,键盘会隐藏该文本框。

enter image description hereenter image description here

有没有在SwiftUI中保持文本字段始终在键盘顶部的简单解决方案?
3个回答

5
这里是一个代码片段,观察与键盘相关的NotificationCenter通知,并根据计算得出的键盘高度来更改间隔视图的高度。
import Combine
struct ExampleView: View {

  @State var keyboardHeight: CGFloat = 0
  var cancellables: Set<AnyCancellable> = []

  init() {
      NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)
        .merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
        .compactMap({ notification in
          guard let keyboardFrameValue: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return nil }
          let keyboardFrame = keyboardFrameValue.cgRectValue
          // If the rectangle is at the bottom of the screen, set the height to 0.
          if keyboardFrame.origin.y == UIScreen.main.bounds.height {
            return 0
          } else {
            // Adjust for safe area
            return keyboardFrame.height - (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
          }
        })
        .assign(to: \.keyboardHeight, on: self)
        .store(in: &cancellables)
  }

  var body: some View {
    VStack {

      // Your content here

      Spacer()
        .frame(height: keyboardHeight)
    }
  }
}

我写了一个处理此事的Swift包,它公开了一个KeyboardObservingView来包装您的内容。

该包在这里可用:https://github.com/nickffox/KeyboardObserving

您可以像这样使用它:

var body: some View {
  KeyboardObservingView {
    List {...}
    TextField("Placeholder", text: .constant(""))
      .frame(minHeight: 30)
      .cornerRadius(8.0)
      .padding(10)
      .background(Color.blue)
  }
}

下面是使用该软件包的图示: 演示


程序相关内容的翻译:崩溃了 致命错误:在View.body之外访问State<CGFloat>:文件 - Kevin ABRIOUX

4

我已经尝试过不同的方法,但都无法正常工作。下面这种方法是唯一适用于不同设备上的方法。

将以下扩展名添加到文件中:

    import SwiftUI
    import Combine

    extension View {

      func keyboardSensible(_ offsetValue: Binding<CGFloat>) -> some View {

        return self
            .padding(.bottom, offsetValue.wrappedValue)
            .animation(.spring())
            .onAppear {
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { notification in

                let keyWindow = UIApplication.shared.connectedScenes
                    .filter({$0.activationState == .foregroundActive})
                    .map({$0 as? UIWindowScene})
                    .compactMap({$0})
                    .first?.windows
                    .filter({$0.isKeyWindow}).first

                let bottom = keyWindow?.safeAreaInsets.bottom ?? 0

                let value = notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
                let height = value.height

                offsetValue.wrappedValue = height - bottom
            }

            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { _ in
                offsetValue.wrappedValue = 0
            }
        }
      }
}

在您的观点中,您需要一个变量来绑定offsetValue:
struct IncomeView: View {

  @State private var offsetValue: CGFloat = 0.0

  var body: some View { 

    VStack {
     //...       
    }
    .keyboardSensible($offsetValue)
  }
}

好的方法。谢谢。 - FRIDDAY

-1

我来分享一个简单、易懂但有点 hacky 的解决方案,用于处理键盘相关的问题:

struct ContentView : View {

 @State private var name = ""
 @State private var keyboardUp = false
 private var keyboardHeight: CGFloat { 150 }

    var body: some View {
        NavigationView {
            Spacer()
            Form {
                TextField($name, placeholder: Text("Name"), onEditingChanged: { { self.keyboardUp = $0 })
            }.offset(y: keyboardUp ? -keyboardHeight : 0)
            .animation(.basic())
            .navigationBarTitle(Text("Title"))
        }
    }
}

这个解决方案并不适用于所有设备,因为不同设备上的键盘大小可能会有所不同。 - VSMelo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接