繁体   English   中英

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

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

如何防止UITextField被键盘隐藏?

我假设这发生在UIViewController 如果是这样,您可以设置在键盘显示/隐藏时调用以下两个函数,并在它们的块中做出适当的响应。

设置UIViewController

class ViewController: UIViewController, UITextFieldDelegate... {

    var frameView: UIView!

首先,在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)

}

然后实现下面两个函数来响应你上面viewDidLoad()定义的NotificationCenter函数。 我给你一个移动整个视图的例子,但你也可以只为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)

}

离开视图时不要忘记删除通知

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

这是 Swift 中的简单解决方案。 我翻译了一些过去对我有用的 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 的代码,非常简单,而不是使用NSNotificationCenter之类的很多东西,然后计算所有东西的高度和制作条件使这个变得更加复杂,

执行此操作的简单方法如下所示,它将向上移动视图。

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

您可以根据文本字段的位置更改 -250 值。

如果您使用UIScrollView或其任何子类,例如UITableView ,您还可以操作contentInset属性。 这样你就不必弄乱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)
}

斯威夫特 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
    }

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

只需将“IQKeyboardManager”库添加到您的项目中,就完成了。 你不必做任何其他事情。 作为参考,请检查此网址。

https://github.com/hackiftekhar/IQKeyboardManager

Swift 4我已经看到了很多答案,其中很多对我来说都不起作用,因为我有一个带有大量文本字段的 UIViewController。

根据Apple 文档,我已将示例翻译为 Swift 4

您的内容需要嵌入到滚动视图中。

添加键盘何时出现或消失的通知侦听器。

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

实现 UITextField 委托

func textFieldDidBeginEditing(_ textField: UITextField) {

    currentTextField = textField
}

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

    currentTextField = nil

}

选择器

@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

}

首先你应该有scrollview步骤1:找到键盘的高度

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

第二步:绑定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代码

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 它将处理表格视图中的所有文本字段。

查看我的要点,我在我的案例中使用了 scrollView,但它适用于任何类型的视图,您只需删除 scrollView 部分并将其替换为您的视图。 要点的评论非常好,因此您还将了解如何处理此案例。 https://gist.github.com/Sjahriyar/916e93153a29dc602b45f29d39182352

我创建了KeyboardController来处理键盘问题。 需要做的就是调用setUpKeyBoardListeners()并将lastElement设置为视图中的最后一个元素。

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

暂无
暂无

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

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