TextField always on keyboard top with SwiftUI

五迷三道 提交于 2019-12-12 10:15:34

问题


i have this

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

Actually, when i focus on the TextField, keyboard hide this textfield.

Is there a simple solution in SwiftUI to keep the textfield always on keyboard's top ?


回答1:


Here is a snippet that observes NotificationCenter notifications related the keyboard, and changes the height of a spacer view based on the computed keyboard height.

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

I wrote a Swift package that handles this for you. It exposes a KeyboardObservingView that wraps your content.

It's available here: https://github.com/nickffox/KeyboardObserving

You would use it like this:

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

Here's an image of the package in use: demo




回答2:


Just gonna drop a simple, easy and a bit hacky solution I found to handle the keyboard:

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



回答3:


I am not sure 100% about the SwiftUI but I have a scroll view and I am using this function to keep my text field and button always top of the keyboard

    //function for scroll view to adjust when is keyboard is appeared so the text field stays above the keyboard      
    @objc func adjustForKeyboard(notification: Notification) {
            guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }

            let keyboardScreenEndFrame = keyboardValue.cgRectValue
            let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)

            if notification.name == UIResponder.keyboardWillHideNotification {
                scrollView.contentInset = .zero
            } else {
                if #available(iOS 11.0, *) {
                    scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - view.safeAreaInsets.bottom, right: 0)
                }
            }
            scrollView.scrollIndicatorInsets = scrollView.contentInset
        }

You can use this by calling like this with UIResponder and selector on your viewDidLoad.

//register for keyboard change notifications when text field is being used
        NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)


来源:https://stackoverflow.com/questions/57497477/textfield-always-on-keyboard-top-with-swiftui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!