我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
当前回答
斯威夫特4:
我有一个问题与最接受的答案,其中隐藏键盘并没有返回视图一直到页面的底部(只是部分)。这对我来说很有效(+为Swift 4更新)。
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y = 0
}
}
}
其他回答
当打开键盘时,它100%完美地回答了所有人的更新表视图高度
对于Swift4.2
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.tbl.contentInset
contentInset.bottom = keyboardFrame.size.height
self.tbl.contentInset = contentInset
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.tbl.contentInset = contentInset
}
}
Swift3.2
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
//self.view.frame.origin.y -= keyboardSize.height
var userInfo = notification.userInfo!
var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = self.tbl.contentInset
contentInset.bottom = keyboardFrame.size.height
self.tbl.contentInset = contentInset
}
}
func keyboardWillHide(notification: NSNotification) {
if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
self.tbl.contentInset = contentInset
}
}
对于黑屏错误(Swift 4和4.2)。
我解决了黑屏的问题。在验证方案中,敲击后键盘高度变化,导致黑屏。
必须使用UIKeyboardFrameEndUserInfoKey而不是UIKeyboardFrameBeginUserInfoKey
var isKeyboardAppear = false
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if !isKeyboardAppear {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0{
self.view.frame.origin.y -= keyboardSize.height
}
}
isKeyboardAppear = true
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if isKeyboardAppear {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y != 0{
self.view.frame.origin.y += keyboardSize.height
}
}
isKeyboardAppear = false
}
}
我已经阅读了答案,并通过以下代码行解决了我的问题:
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var titleField: UITextField!
@IBOutlet weak var priceField: UITextField!
@IBOutlet weak var detailsField: UTtextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do not to forget to set the delegate otherwise the textFieldShouldReturn(_:)
// won't work and the keyboard will never be hidden.
priceField.delegate = self
titleField.delegate = self
detailsField.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow),
name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide),
name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
func keyboardWillShow(notification: NSNotification) {
var translation:CGFloat = 0
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if detailsField.isEditing{
translation = CGFloat(-keyboardSize.height)
}else if priceField.isEditing{
translation = CGFloat(-keyboardSize.height / 3.8)
}
}
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: translation)
}
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.2) {
self.view.transform = CGAffineTransform(translationX: 0, y: 0)
}
}
}
我有几个UITextFields,并希望视图移动不同取决于哪个textField被点击。
我们对KeyboardWillHideNotification的定义做了一些改变。
此解决方案适用于Swift 4.2:
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
@objc func keyboardWillShow(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.view.frame.origin.y -= keyboardSize.height
}
}
@objc func keyboardWillHide(_ notification:Notification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.view.frame.origin.y += keyboardSize.height
}
}
斯威夫特5.0:
经过4-5个小时的战斗,我得到了一个简单的扩展UIViewController与简单的代码,就像魅力
*当TextField在键盘上方时,视图不应该移动
*不需要设置常量值为NSLayoutConstraint
*无需第三方库
*无需动画代码
*适用于tableview
*这适用于自动布局/自动调整大小
extension UIViewController {
func addKeyboardObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotifications(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}
func removeKeyboardObserver(){
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
// This method will notify when keyboard appears/ dissapears
@objc func keyboardNotifications(notification: NSNotification) {
var txtFieldY : CGFloat = 0.0 //Using this we will calculate the selected textFields Y Position
let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
// Here we will get accurate frame of textField which is selected if there are multiple textfields
frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
txtFieldY = frame.origin.y + frame.size.height
}
if let userInfo = notification.userInfo {
// here we will get frame of keyBoard (i.e. x, y, width, height)
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyBoardFrameY = keyBoardFrame!.origin.y
let keyBoardFrameHeight = keyBoardFrame!.size.height
var viewOriginY: CGFloat = 0.0
//Check keyboards Y position and according to that move view up and down
if keyBoardFrameY >= UIScreen.main.bounds.size.height {
viewOriginY = 0.0
} else {
// if textfields y is greater than keyboards y then only move View to up
if txtFieldY >= keyBoardFrameY {
viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard
//This condition is just to check viewOriginY should not be greator than keyboard height
// if its more than keyboard height then there will be black space on the top of keyboard.
if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
}
}
//set the Y position of view
self.view.frame.origin.y = -viewOriginY
}
}
}
添加这个扩展的UIResponder得到哪个TextField被选中
extension UIResponder {
static weak var responder: UIResponder?
static func currentFirst() -> UIResponder? {
responder = nil
UIApplication.shared.sendAction(#selector(trap), to: nil, from: nil, for: nil)
return responder
}
@objc private func trap() {
UIResponder.responder = self
}
}
然后在你的任何ViewController中使用这个
override func viewWillAppear(_ animated: Bool) {
self.addKeyboardObserver()
}
override func viewWillDisappear(_ animated: Bool) {
self.removeKeyboardObserver()
}
在func viewWillAppear中注册这个通知(_ animated: Bool) 在func中注销此通知viewWillDisappear(_ animated:Bool) 下载演示文件