简体   繁体   English

存在键盘时如何使 UITextField 向上移动?

[英]How to make UITextField move up when keyboard is present?

如何防止UITextField被键盘隐藏?

I assume this is happening on a UIViewController .我假设这发生在UIViewController If so, you can setup the following two functions to be called when the keyboard will show/hide, and respond appropriately in their blocks.如果是这样,您可以设置在键盘显示/隐藏时调用以下两个函数,并在它们的块中做出适当的响应。

Setting up the UIViewController :设置UIViewController

class ViewController: UIViewController, UITextFieldDelegate... {

    var frameView: UIView!

First, in viewDidLoad() :首先,在viewDidLoad()

override func viewDidLoad() {

    self.frameView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height))

    // Keyboard stuff.
    let center: NotificationCenter = NotificationCenter.default
    center.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    center.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)

}

Then implement the following two functions to respond to your NotificationCenter functions defined in viewDidLoad() above.然后实现下面两个函数来响应你上面viewDidLoad()定义的NotificationCenter函数。 I give you an example of moving the entire view, but you can also animate just the UITextField s.我给你一个移动整个视图的例子,但你也可以只为UITextField设置动画。

@objc func keyboardWillShow(notification: NSNotification) {
    let info:NSDictionary = notification.userInfo! as NSDictionary
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

    let keyboardHeight: CGFloat = keyboardSize.height

    let _: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat


    UIView.animate(withDuration: 0.25, delay: 0.25, options: .curveEaseInOut, animations: {
        self.frameView.frame = CGRect(x: 0, y: (self.frameView.frame.origin.y - keyboardHeight), width: self.view.bounds.width, height: self.view.bounds.height)
    }, completion: nil)
}

@objc func keyboardWillHide(notification: NSNotification) {
    let info: NSDictionary = notification.userInfo! as NSDictionary
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

    let keyboardHeight: CGFloat = keyboardSize.height

    let _: CGFloat = info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat

    UIView.animate(withDuration: 0.25, delay: 0.25, options: .curveEaseInOut, animations: {
        self.frameView.frame = CGRect(x: 0, y: (self.frameView.frame.origin.y + keyboardHeight), width: self.view.bounds.width, height: self.view.bounds.height)
    }, completion: nil)

}

Don't forget to remove the notifications when leaving your view离开视图时不要忘记删除通知

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

Here is the simple solution in Swift.这是 Swift 中的简单解决方案。 I translated some Objective-C code that worked for me in the past.我翻译了一些过去对我有用的 Objective-C 代码。

func textFieldDidBeginEditing(textField: UITextField) { // became first responder

    //move textfields up
    let myScreenRect: CGRect = UIScreen.mainScreen().bounds
    let keyboardHeight : CGFloat = 216

    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:NSTimeInterval = 0.35
    var needToMove: CGFloat = 0

    var frame : CGRect = self.view.frame
    if (textField.frame.origin.y + textField.frame.size.height + /*self.navigationController.navigationBar.frame.size.height + */UIApplication.sharedApplication().statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight)) {
    needToMove = (textField.frame.origin.y + textField.frame.size.height + /*self.navigationController.navigationBar.frame.size.height +*/ UIApplication.sharedApplication().statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight);
    }

    frame.origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(textField: UITextField) {
        //move textfields back down
        UIView.beginAnimations( "animateView", context: nil)
        var movementDuration:NSTimeInterval = 0.35
        var frame : CGRect = self.view.frame
        frame.origin.y = 0
        self.view.frame = frame
        UIView.commitAnimations()
}

Swift 4 code, It is very simple instead of using many things like NSNotificationCenter, then calculating the height of everything and making conditions makes this more complicated, Swift 4 的代码,非常简单,而不是使用NSNotificationCenter之类的很多东西,然后计算所有东西的高度和制作条件使这个变得更加复杂,

The Simple way to do this is coded below, it will work to move up the view.执行此操作的简单方法如下所示,它将向上移动视图。

func textFieldDidBeginEditing(_ textField: UITextField) {
        moveTextField(textfield: textField, moveDistance: -250, up: true)
}

func textFieldDidEndEditing(_ textField: UITextField) {
        moveTextField(textfield: textField, moveDistance: -250, up: false)
}

func moveTextField(textfield: UITextField, moveDistance: Int, up: Bool) {
    let moveDuration = 0.3
    let movement: CGFloat = CGFloat(up ? moveDistance: -moveDistance)
    UIView.beginAnimations("animateTextField", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(moveDuration)
    self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
    UIView.commitAnimations()
}

you can change that -250 value according to the placement of your textfields.您可以根据文本字段的位置更改 -250 值。

In case you are using a UIScrollView or any of its subclasses, eg, UITableView , you can also manipulate the contentInset property.如果您使用UIScrollView或其任何子类,例如UITableView ,您还可以操作contentInset属性。 That way you do not have to mess with frame , bounds , NSLayoutConstraint or NSLayoutAnchor .这样你就不必弄乱frameboundsNSLayoutConstraintNSLayoutAnchor

func keyboardWillShow(notification: Notification) {
    let info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    let keyboardHeight: CGFloat = keyboardSize.height
    let duration = info[UIKeyboardAnimationDurationUserInfoKey] as! TimeInterval
    UIView.animate(withDuration: duration, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
        self.tableView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0)
    }, completion: nil)
}

func keyboardWillHide(notification: Notification) {
    let info = notification.userInfo!
    let duration = info[UIKeyboardAnimationDurationUserInfoKey] as! TimeInterval
    UIView.animate(withDuration: duration, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
        self.tableView?.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }, completion: nil)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

Swift 3.0斯威夫特 3.0

 var activeField: UITextField?

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    func textFieldDidBeginEditing(_ textField: UITextField){
        activeField = textField
    }

    func textFieldDidEndEditing(_ textField: UITextField){
        activeField = nil
    }

    func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            if (self.activeField?.frame.origin.y)! >= keyboardSize.height {
                self.view.frame.origin.y = keyboardSize.height - (self.activeField?.frame.origin.y)!
            } else {
                self.view.frame.origin.y = 0
            }
        }
    }

    func keyboardWillHide(notification: NSNotification) {
        self.view.frame.origin.y = 0
    }

In Swift 3 use this code在 Swift 3 中使用此代码

  override func viewDidLoad() {
        super.viewDidLoad()

                let center: NotificationCenter = NotificationCenter.default
        center.addObserver(self, selector: #selector(RFLogInViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        center.addObserver(self, selector: #selector(RFLogInViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }



 func keyboardWillShow(notification: NSNotification) {
        let info:NSDictionary = notification.userInfo! as NSDictionary
        let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

        let keyboardHeight: CGFloat = keyboardSize.height

        let _: CGFloat = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat


        UIView.animate(withDuration: 0.25, delay: 0.25, options: .curveEaseInOut, animations: {
            self.view.frame = CGRect(x: 0, y: (self.view.frame.origin.y - keyboardHeight), width: self.view.bounds.width, height: self.view.bounds.height)
        }, completion: nil)

    }




 func keyboardWillHide(notification: NSNotification) {
        let info: NSDictionary = notification.userInfo! as NSDictionary
        let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

        let keyboardHeight: CGFloat = keyboardSize.height

        let _: CGFloat = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber as! CGFloat

        UIView.animate(withDuration: 0.25, delay: 0.25, options: .curveEaseInOut, animations: {

              self.view.frame = CGRect(x: 0, y: (self.view.frame.origin.y + keyboardHeight), width: self.view.bounds.width, height: self.view.bounds.height)
        }, completion: nil)

    }


  override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

Just add 'IQKeyboardManager' library into your project, and Done.只需将“IQKeyboardManager”库添加到您的项目中,就完成了。 You have not to do anything else.你不必做任何其他事情。 For reference please check this url.作为参考,请检查此网址。

https://github.com/hackiftekhar/IQKeyboardManager https://github.com/hackiftekhar/IQKeyboardManager

Swift 4 I have seen numerous of answer and plenty of them did not work for me where I have a UIViewController With numerous of text fields. Swift 4我已经看到了很多答案,其中很多对我来说都不起作用,因为我有一个带有大量文本字段的 UIViewController。

According to the Apple documentation I have translate the example to Swift 4根据Apple 文档,我已将示例翻译为 Swift 4

Your content needs to be embedded within an scrollview.您的内容需要嵌入到滚动视图中。

Add the notification listeners for when the keyboard will appear or dissappear.添加键盘何时出现或消失的通知侦听器。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: .UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}

Implement UITextField Delegates实现 UITextField 委托

func textFieldDidBeginEditing(_ textField: UITextField) {

    currentTextField = textField
}

func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {

    currentTextField = nil

}

Selectors选择器

@objc func keyboardDidShow(notification: NSNotification) {
    print("\(logClassName): keyboardWDidShow")

    let keyboardFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

    let keyboardSize:CGSize = keyboardFrame!.size

    let contentInsets:UIEdgeInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    trackScrollView.contentInset = contentInsets
    trackScrollView.scrollIndicatorInsets = contentInsets

    var aRect:CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height

    if !(aRect.contains(currentTextField!.frame.origin)){

        trackScrollView.scrollRectToVisible(currentTextField!.frame, animated: true)

    }

}

@objc func keyboardWillHide(notification: NSNotification){

    print("\(logClassName): keyboardWillHide")

    let contentInsents:UIEdgeInsets = UIEdgeInsets.zero
    trackScrollView.contentInset = contentInsents
    trackScrollView.scrollIndicatorInsets = contentInsents

}

first of all you should have scrollview step 1:find the height of key board首先你应该有scrollview步骤1:找到键盘的高度

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo ? [UIKeyboardFrameBeginUserInfoKey] as ? NSValue) ? .cgRectValue {
        let keyboardHeight = keyboardSize.height
        a = keyboardHeight
    }
}

step 2: bind the delegete methods of textfield第二步:绑定textfield的delegete方法

func textFieldDidBeginEditing(_ textField: UITextField) {
    utility.setUserDefaultBool(value: false, key: "FrameMoveFlag") //flag
    let b = view1.frame.height - textField.frame.origin.y
    if (b < 350) {
        view1.frame.origin.y = view1.frame.origin.y + (view1.frame.height - textField.frame.origin.y) - (a + 50)
        utility.setUserDefaultBool(value: true, key: "FrameMoveFlag") //flag
    }
}

func textFieldDidEndEditing(_ textField: UITextField) {
    if (utility.getUserDefaultBOOLForKey(key: "FrameMoveFlag") == true) {
        view1.frame.origin.y = 0
    }
}

Swift 3 code for Geiger answer盖革答案的Swift 3代码

func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder

    //move textfields up
    let myScreenRect: CGRect = UIScreen.main.bounds
    let keyboardHeight : CGFloat = 216

    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var needToMove: CGFloat = 0

    var frame : CGRect = self.view.frame
    if (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
        needToMove = (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
    }

    frame.origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(_ textField: UITextField) {
    //move textfields back down
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var frame : CGRect = self.view.frame
    frame.origin.y = 0
    self.view.frame = frame
    UIView.commitAnimations()
}

如果您不想手动处理键盘的出现和消失,只需使用 UITableViewController 它将处理表格视图中的所有文本字段。

Check out my gist, I use a scrollView for my case, but it works for any kind of view, you only have to remove the scrollView part and replace it with your view.查看我的要点,我在我的案例中使用了 scrollView,但它适用于任何类型的视图,您只需删除 scrollView 部分并将其替换为您的视图。 The gist is very well commented so you will also understand how this case is handled.要点的评论非常好,因此您还将了解如何处理此案例。 https://gist.github.com/Sjahriyar/916e93153a29dc602b45f29d39182352 https://gist.github.com/Sjahriyar/916e93153a29dc602b45f29d39182352

I created KeyboardController to handle the keyboard issue.我创建了KeyboardController来处理键盘问题。 All that needs to be done is call setUpKeyBoardListeners() and set the lastElement as whatever the last element in your view is.需要做的就是调用setUpKeyBoardListeners()并将lastElement设置为视图中的最后一个元素。

Gist: https://gist.github.com/espitia/ef830cf677fa1bc33ffdf16ac12d0204要点: https : //gist.github.com/espitia/ef830cf677fa1bc33ffdf16ac12d0204

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM