【问题标题】:Why the two CGRect don't intersect when they do visually?为什么两个 CGRect 在视觉上不相交?
【发布时间】:2016-04-21 17:34:41
【问题描述】:

我正在构建一个应用程序。它需要接受来自一些UITextFields 的用户输入。有时键盘会隐藏文本字段,所以当键盘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 的屏幕截图:

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

经过一些调试,我发现

CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)

返回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,但还是不行。

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

【问题讨论】:

  • 如果您将视图控制器设为UITableViewController 的子类,并使用带有静态单元格的表格视图进行布局,您可能会更轻松。然后表格视图控制器会自动为您处理键盘调整。
  • @robmayoff 我对您的建议有一些疑问。实际上我的标签和文本字段是动态生成的。所以我必须使用原型表视图。那行得通吗?此外,如果我使用您的建议,我需要以编程方式将标签和文本字段添加到表格视图单元格。我对吗?如果没有,你能简单解释一下如何使用原型表视图控制器来做到这一点吗?
  • 是的,您可以使用基于原型的表格视图。您可以使用标签和文本字段在情节提要中设计原型单元格。

标签: ios iphone swift keyboard rect


【解决方案1】:

问题是在这段代码中:

CGRectIntersectsRect(focusedTextField!.bounds, keyboardSize)

...你在比较苹果和橘子:

  • focusedTextField!.boundsfocusedTextField的坐标空间中

  • keyboardSize窗口的坐标空间

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

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

例如,我认为这样就可以了:

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

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-09-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多