单击已显示键盘的第二个UITextField会错误地移动内容

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单击已显示键盘的第二个UITextField会错误地移动内容相关的知识,希望对你有一定的参考价值。

编辑:添加了请求的方法。

更新:当我单击输入1时,将调用keyboardwillchange回调一次。当我在没有先解除键盘的情况下点击第二个输入时,由于某种原因,键盘会切换回调被称为TWICE。另外,我注意到我的代码仍在计算正确的帧。然而,似乎xcode忽略了这一点,或者只是覆盖并将事情重新置于它们最初的构造方式。

我的屏幕顶部有一些图像内容,2个文本字段,下半部分有文本视图。输入位于堆栈视图中。每当我单击文本字段/视图时,我都会将堆栈视图向上移动得足够远,以便所有输入都可见。当我关闭键盘时,堆栈视图会回到原来的位置。这很棒!当我单击一个文本字段(常规键盘)然后单击另一个文本字段(数字键盘)时,我的堆栈视图将返回原始位置,此时它根本不应移动。为了尝试修复此问题,我添加了一些布尔值来跟踪键盘是否显示并使用它来阻止我的UIKeyboardWillShow方法做任何事情。

什么是Xcode 9.1 / Swift 4,我可以阻止它发生?

旁注:我尝试使用IQKeyboardManager,但它似乎不允许我阻止顶部图像内容移动太多。

我的相关代码:

class MoodEntryVC: UIViewController, UITextFieldDelegate, UITextViewDelegate {

@IBOutlet weak var questionsStackView: UIStackView!
@IBOutlet weak var hoursTextField: UITextField!
@IBOutlet weak var locationTextField: UITextField!
@IBOutlet weak var otherInfoTextView: UITextView!
@IBOutlet weak var headerBarView: UIView!
@IBOutlet weak var bgHeaderView: UIImageView!

var currentTextField: UITextField?
var currentTextView: UITextView?
var currentBGHeaderFrame: CGRect!
var currentQuestionsStackFrame: CGRect!
var currentFieldEditing: FieldType!
var keyboardVisible: Bool = false

override func viewDidLoad() {
    super.viewDidLoad()
    hideKeyboardWhenTappedAround2()

    locationTextField.delegate = self
    hoursTextField.delegate = self
    otherInfoTextView.delegate = self

    currentBGHeaderFrame = bgHeaderView.frame
    currentQuestionsStackFrame = questionsStackView.frame

    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}

fileprivate func moveQuestionsAndBGHeader(_ newTopY: CGFloat, _ bgNewTopY: CGFloat) {
    UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
        let newRect = CGRect(x: self.questionsStackView.frame.origin.x, y: newTopY, width: self.questionsStackView.bounds.width, height: self.questionsStackView.bounds.height)
        self.questionsStackView.frame = newRect
        self.bgHeaderView.frame = CGRect(x: self.bgHeaderView.frame.origin.x, y: bgNewTopY, width: self.bgHeaderView.bounds.width, height: self.bgHeaderView.bounds.height)
    }, completion: nil)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    UIView.animate(withDuration: 1.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
        textField.resignFirstResponder()
    }, completion: nil)
    return true
}

@objc func keyboardDidShow(_ notification: NSNotification) {
    keyboardVisible = true
}

@objc func keyboardWillChangeFrame(_ notification: NSNotification) {
    print("keyboard will change")
}

@objc func keyboardWillShow(_ notification: NSNotification) {        
    if keyboardVisible {
        return
    }

    // Get keyboard sizing
    let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

    // Get data entry view sizing
    let topY = questionsStackView.frame.origin.y
    let bottomY = questionsStackView.frame.height + topY
    let newTopY = endFrame.origin.y - 10 - questionsStackView.frame.height

    // Get bgHeaderView sizing
    let bgTopY = bgHeaderView.frame.origin.y
    let bgBottomY = bgHeaderView.frame.height + bgTopY
    let gapToDataEntry = topY - bgBottomY
    let bgNewTopY = newTopY - gapToDataEntry - bgHeaderView.frame.height

    // This moves the stack view to the correct location above the keyboard
    moveQuestionsAndBGHeader(newTopY, bgNewTopY)
}

@objc func keyboardWillHide(_ notification: NSNotification) {
    UIView.animate(withDuration: 1.3, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
       self.moveQuestionsAndBGHeader(self.currentQuestionsStackFrame.origin.y, self.currentBGHeaderFrame.origin.y)
         self.view.endEditing(true)
    }, completion: nil)
    keyboardVisible = false
}

谢谢!

答案

尝试添加此方法

func textFieldDidEndEditing(textField: UITextField) {
    view.endEditing(true)
}

当第一个文本字段将变为活动状态时,键盘将隐藏。类似地,当其他文本字段将变为活动状态时,键盘将显示。

以上是关于单击已显示键盘的第二个UITextField会错误地移动内容的主要内容,如果未能解决你的问题,请参考以下文章

成为没有动画的第一响应者

点击另一个 UITextField 后自动禁用键盘

无法通过单击选择文本字段(Swift)

如何在第二个视图控制器上显示核心数据?

UITextField 不接收文本更改

使用UITextField + UIPickerview时禁用键盘输入