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

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

我跟着这个教程 ,我添加了一些我自己的逻辑,因为我有多个文本字段。

这里是我的相关代码:(整个事情是在符合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的类级variables。然后检查焦点文本字段(记住?)是否被键盘覆盖(通过CGRectIntersectRect )。 如果是这样,我们通过调用moveView移动视图。 这个方法非常好,所以不需要解释。

现在解决问题了!

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

在这里输入图像说明

当我点击“inputA”文本字段时,视图按预期向上移动。 但是,当我点击“inputP”文本字段,键盘显示并完全覆盖文本字段。

经过一些debugging,我发现

CGRectIntersectsRect(focusedTextField!.bounds,keyboardSize)

返回false所以moveView不被调用。 “inputP”文本字段和键盘大小如下所示:

 Bounds of text field: x: 62 y: 94.5 height: 32.5 width: 278 Keyboard size: x: 0 y: 158 height: 162 width: 568 

只是从这些数字,我不认为它们重叠。 但在视觉上,他们真的这样做!

在这里输入图像说明

我也尝试将focusedTextField!.bounds改为focusedTextField.frame但它仍然不起作用。

为什么发生这种情况? 我如何解决它?

问题是在这个代码中:

 CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize) 

…你在比较苹果和橘子:

  • focusedTextField!.bounds位于focusedTextField!.bounds的坐标空间中

  • keyboardSize位于窗口的坐标空间中

(而且,为什么focusedTextField.frame的原因是它在另一个坐标空间,即文本字段的超视图。

这是两个非常不同的坐标空间,所以你不能比较这些反应。 您必须其中一个转换为另一个的坐标空间。

例如,我认为这将做到这一点:

 newKeyboardSize = focusedTextField.convertRect(keyboardSize, fromView:nil) 

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

Interesting Posts