为什么两个 CGRect 在视觉上不相交?
Why the two CGRect don't intersect when they do visually?
我正在构建一个应用程序。它需要接受来自一些 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
的 class 级变量,然后检查焦点文本字段(还记得吗?)是否被键盘覆盖(通过 CGRectIntersectRect
) .如果是,那么我们通过调用 moveView
向上移动视图。该方法非常有效,因此无需解释。
现在进入正题!
让我们看一下 VC:
的屏幕截图
当我点击 "Enter A" 文本字段时,视图按预期向上移动。但是当我点击 "Enter P" 文本字段时,键盘出现并完全覆盖了文本字段。
经过一番调试,我发现
CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)
returns false
所以 moveView
没有被调用。 "Enter 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
仅从这些数字来看,我认为它们没有重叠。但从视觉上看,他们确实做到了!
我也试过把focusedTextField!.bounds
改成focusedTextField.frame
,还是不行。
为什么会这样?我该如何解决?
问题是在这段代码中:
CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)
...你在比较苹果和橘子:
focusedTextField!.bounds
在focusedTextField
的坐标space
keyboardSize
在的坐标space中window
(focusedTextField.frame
不起作用的原因是它还在 另一个 坐标 space 中,即文本字段的超级视图。 )
这是两个非常不同的坐标 space,因此您无法比较这些矩形。您必须将其中一个转换为另一个的坐标space。
例如,我认为这样就可以了:
newKeyboardSize = focusedTextField.convertRect(keyboardSize, fromView:nil)
现在newKeyboardSize
和focusedTextField.bounds
应该在同一个坐标space.
我正在构建一个应用程序。它需要接受来自一些 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
的 class 级变量,然后检查焦点文本字段(还记得吗?)是否被键盘覆盖(通过 CGRectIntersectRect
) .如果是,那么我们通过调用 moveView
向上移动视图。该方法非常有效,因此无需解释。
现在进入正题!
让我们看一下 VC:
的屏幕截图当我点击 "Enter A" 文本字段时,视图按预期向上移动。但是当我点击 "Enter P" 文本字段时,键盘出现并完全覆盖了文本字段。
经过一番调试,我发现
CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)
returns false
所以 moveView
没有被调用。 "Enter 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
仅从这些数字来看,我认为它们没有重叠。但从视觉上看,他们确实做到了!
我也试过把focusedTextField!.bounds
改成focusedTextField.frame
,还是不行。
为什么会这样?我该如何解决?
问题是在这段代码中:
CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)
...你在比较苹果和橘子:
focusedTextField!.bounds
在focusedTextField
的坐标space
keyboardSize
在的坐标space中window
(focusedTextField.frame
不起作用的原因是它还在 另一个 坐标 space 中,即文本字段的超级视图。 )
这是两个非常不同的坐标 space,因此您无法比较这些矩形。您必须将其中一个转换为另一个的坐标space。
例如,我认为这样就可以了:
newKeyboardSize = focusedTextField.convertRect(keyboardSize, fromView:nil)
现在newKeyboardSize
和focusedTextField.bounds
应该在同一个坐标space.