键盘覆盖视图底部的文本字段

时间:2017-09-30 06:24:14

标签: ios swift view keyboard textfield

我搜索了

此处:Move a view up only when the keyboard covers an input field

此处:Move textfield when keyboard appears swift

此处:How to make a UITextField move up when keyboard is present?

在这里:https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

不幸的是,所有链接和我能找到的其他地方似乎并没有提供我正在寻找的良好清洁解决方案。它们要么使用Obj-c代码过时,要么在 Xcode 9 的当前迭代中使用 Swift 4 无效。

如何管理覆盖视图底部文本字段的键盘?我希望屏幕视图仅在键盘覆盖文本字段视图时移动,不使用滚动视图,能够为其设置动画以使其看起来漂亮而不是仅仅快照,最重要的是我不想使用外部库

来自Apple的CoreAnimation库非常棒,但所有示例代码都已过时,而且客观c在此时已被弃用(我不相信Apple不会更新他们的文档)。

如果有人能指出我正确的方向更新当前代码或Apple的图书馆,我将失踪,这将特别解决这个问题,我们将不胜感激。

5 个答案:

答案 0 :(得分:7)

您可以使用IQKeyboardManagerSwift轻松快速地解决您的问题。

在pod文件中使用以下pod,它支持Swift 4。

pod 'IQKeyboardManagerSwift', '5.0.0'

这是实现IQKeyboardManagerSwift的链接。

https://github.com/hackiftekhar/IQKeyboardManager

感谢!!!

答案 1 :(得分:3)

此代码可以正常工作,如果textField的框架与键盘相交并动画回键盘隐藏的原始位置,则将textField设置为键盘上方的动画。

@IBOutlet weak var textField: UITextField!

  var offsetY:CGFloat = 0

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardFrameChangeNotification(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
  }

  func keyboardFrameChangeNotification(notification: Notification) {
    if let userInfo = notification.userInfo {
      let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? CGRect
      let animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double ?? 0
      let animationCurveRawValue = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as? Int) ?? Int(UIViewAnimationOptions.curveEaseInOut.rawValue)
      let animationCurve = UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue))
      if let _ = endFrame, endFrame!.intersects(self.textField.frame) {
        self.offsetY = self.textField.frame.maxY - endFrame!.minY
        UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
          self.textField.frame.origin.y = self.textField.frame.origin.y - self.offsetY
        }, completion: nil)
      } else {
        if self.offsetY != 0 {
          UIView.animate(withDuration: animationDuration, delay: TimeInterval(0), options: animationCurve, animations: {
            self.textField.frame.origin.y = self.textField.frame.origin.y + self.offsetY
            self.offsetY = 0
          }, completion: nil)
        }
      }
    }
  }

答案 2 :(得分:2)

这段代码对我有用。

如果是多个文字字段

我只针对位于底部的文本字段(不使用通知观察者)实现。

  

如果您使用的是 scrollView ,则此代码可能会有所帮助   ( scrollViewDidScroll 是可选的)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentSize = CGSize(width: self.scrollView.frame.size.width, height: (scrollView.frame.size.height + 300))// To be more specific, I have used multiple textfields so wanted to scroll to the end.So have given the constant 300.
}

func textFieldDidBeginEditing(_ textField:UITextField) {
    self.scrollView.setContentOffset(textField.frame.origin, animated: true)
}

如果要根据视图设置文本字段位置, 试试这个:

func textFieldDidBeginEditing(_ textField:UITextField){
    textField.frame.origin.y = textField.frame.origin.y - 150 //(If have not used contentsizing the scroll view then exclude this line)default origin takes the texfield to the top of the view.So to set lower textfields to proper position have used the constant 150.
    self.scrollView.setContentOffset(textField.frame.origin, animated: true)
}

专门针对底部的文本字段。在 textFieldDidBeginEditing

中检查其代码值 textfield.tag
func textFieldDidBeginEditing(_ textField:UITextField){
    if textField.tag = 4 { //tag value of the textfield which are at the bottom
        self.scrollView.setContentOffset(textField.frame.origin, animated: true)
    }
}

如果您在tableView中实现了文本字段,请使用下面解释的通知观察器。

  

如果 tableView 中有多个文本字段,最好使用通知观察器

override func viewDidAppear(_ animated: Bool) {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2, animations: {
        // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    })
}

deinit {
    print("denit")
    NotificationCenter.default.removeObserver(self)
}

答案 3 :(得分:0)

为Uiview添加一个扩展:

import UIKit

//将视图绑定到键盘更改 扩展UIView {

func bindToKeyboard(){
    NotificationCenter.default.addObserver(self, selector: #selector(UIView.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}



@objc func keyboardWillChange(_ notification: NSNotification) {
    let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
    let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
    let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let deltaY = targetFrame.origin.y - curFrame.origin.y

    UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
        self.frame.origin.y += deltaY

    },completion: {(true) in
        self.layoutIfNeeded()
    })
}

}

答案 4 :(得分:0)

对我来说很完美: http://www.seemuapps.com/move-uitextfield-when-keyboard-is-presented

如果代表设置正确,

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

    // Finish Editing The Text Field
    func textFieldDidEndEditing(_ textField: UITextField) {
        moveTextField(textField, moveDistance: -250, up: false)
    }

    // Hide the keyboard when the return key pressed
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

    // Move the text field in a pretty animation!
    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()
    }