我正在构建一个应用程序。它需要接受来自UITextField的用户输入。有时键盘会隐藏文本字段,因此当键盘CGRect与文本字段的frame相交时,我需要向上移动视图。

我遵循this tutorial,我添加了一些自己的逻辑,因为我有多个文本字段。

这是我的相关代码:(整个事情都在符合UITextFieldDelegate的VC中)

var focusedTextField: UITextField?
var viewMovedUp = false
var keyboardSize: CGRect!

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("onRotate:"), name:UIDeviceOrientationDidChangeNotification, object: nil);
}

override func viewDidDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}

func textFieldDidBeginEditing(textField: UITextField) {
    focusedTextField = textField
}

func onRotate (notification: NSNotification) {
    view.endEditing(true)
}

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardSize =  (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
            self.keyboardSize = keyboardSize
            assert(focusedTextField != nil)
            if CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize){
                moveView(up: true)
            }
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    if viewMovedUp {
        moveView(up: false)
    }
}

func moveView (up up: Bool) {
    let keyboardHeight = keyboardSize.height
    let movement = (up ? -keyboardHeight : keyboardHeight)

    UIView.animateWithDuration(0.3, animations: {
        self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    })
    viewMovedUp = up
}

如果您不想阅读整个代码,我将解释其要点。 因此,基本上,当用户点击文本字段之一时,就会调用textFieldDidBeginEditing。基本上,将focusedTextField设置为用户正在编辑的文本字段。然后keyBoardWillShow被调用。它获取键盘的大小并将其分配给名为keyboardSize的类级别的变量,然后检查键盘是否覆盖了焦点文本字段(是否记得?)(通过CGRectIntersectRect)。如果是,那么我们通过调用moveView将视图上移。该方法可以很好地工作,因此无需解释。

现在到问题了!

让我们看一下VC的屏幕截图:

ios - 为什么两个CGRect在视觉上不相交?-LMLPHP

当我点击“输入A”文本字段时,视图将按预期方式上移。但是,当我点击“Enter P”文本字段时,键盘会出现并完全覆盖该文本字段。

经过一些调试后,我发现

CGRectIntersectsRect(focusedTextField!.bounds,keyboardSize)

返回false,因此不调用moveView。 “输入P”文本字段和键盘大小如下:
Bounds of text field:
    x: 62 y: 94.5
    height: 32.5 width: 278
Keyboard size:
    x: 0 y: 158
    height: 162 width: 568

仅从这些数字来看,我认为它们并不重叠。但是从视觉上看,它们确实做到了!

ios - 为什么两个CGRect在视觉上不相交?-LMLPHP

我还尝试将focusedTextField!.bounds更改为focusedTextField.frame,但仍然无法正常工作。

为什么会这样呢?我如何解决它?

最佳答案

问题是在这段代码中:

CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)

...您正在比较苹果和橘子:
  • focusedTextField!.boundsfocusedTextField的坐标空间中
  • keyboardSize在窗口
  • 的坐标空间中

    (而focusedTextField.frame不起作用的原因是,它在另一个坐标空间中,即文本字段的Superview坐标空间中。)

    这是两个非常不同的坐标空间,因此您无法比较这些矩形。您必须将其中一个转换为另一个坐标空间。

    例如,我认为这可以做到:
    newKeyboardSize = focusedTextField.convertRect(keyboardSize, fromView:nil)
    

    现在newKeyboardSizefocusedTextField.bounds应该在同一坐标空间中。

    10-08 12:26