一尘不染

UITextField文本跳转iOS 9

swift

简要地说:我有ViewController两个UITextField要素。当loginField为firstResponder时,之后

self.passwordField.becomeFirstResponder()

登录字段中的文本跳到左上角并返回。更奇怪的是:此故障仅在第一时间重现,然后您需要重新创建ViewController以观察此行为

这是故障的视频http://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx

我最终遇到了这个问题(不适用于iOS 9):

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if textField === self.loginField {
        self.loginField.resignFirstResponder()
        // Shitty workaround. Hi, Apple!
        self.loginField.setNeedsLayout()
        self.loginField.layoutIfNeeded()

        self.passwordField.becomeFirstResponder()
        return false
    }

    return true
}

有没有人被这个错误困扰?有什么建议?

键盘通知处理程序

我的主视图是UIScrollView,为此我将底部空间更改为超级视图,因此即使显示键盘,用户也可以滚动所有内容

func keyboardWillShow(notification : NSNotification) {
    let keyboardInfo = notification.userInfo!
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue!

    UIView.animateWithDuration(animDuration, animations: {
        self.scrollViewBottom.constant = keyboardFrame.height
        self.view.layoutIfNeeded()

        let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height
        if offsetY > 0 {
            self.scrollView.contentOffset = CGPointMake(0, offsetY)
        }
    })
}

func keyboardWillHide(notification : NSNotification) {
    self.scrollViewBottom.constant = 0
    self.view.layoutIfNeeded()
}

当我在iOS7中发现键盘通知时,8和9会有很大的不同。因此,在iOS
9中,即使键盘不会显示/隐藏,在更改firstResponder时也会发送通知。另外,当我通过点击textField来更改firstResponder时(而不是在我的代码处理的键盘上点击Next),则只有KeyboardWillShow通知,而没有KeyboardWillHide。对于我来说,userInfo有一些垃圾帧值,这是使用next按钮更改第一响应者时的日志(工作正常,没有故障):

2015-10-07 12:54:13.870
keyboardWillHide:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,568
},{320、216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160、676},UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey
7] -10-07 12:54:13.896
keyboardWillShow:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,352}
,{320、216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{160、460},UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7]

这是我点击第二个textField时的日志:

2015-10-07 12:55:13.879
keyboardWillShow:[UIKeyboardFrameBeginUserInfoKey:NSRect:{{0,352},{320,216}},UIKeyboardCenterBeginUserInfoKey:NSPoint:{160,460},UIKeyboardFrameEndUserInfoKey:NSRect:{{0,352
},{320、216}},UIKeyboardCenterEndUserInfoKey:NSPoint:{
160、460
},UIKeyboardAnimationDurationUserInfoKey:0.25,UIKeyboardIsLocalUserInfoKey:1,UIKeyboardBoundsUserInfoKey:NSRect:{{0,0},{320,216}},UIKeyboardAnimationCurveUserInfoKey:7

解析度

我发现我还有另一个键盘控制器,可以接收键盘通知并制作一些动画。那就是问题所在


阅读 192

收藏
2020-07-07

共1个答案

一尘不染

根据您编辑的问题,当您点击键盘上的下一个按钮时,我会看到以下内容:

  1. 您先打电话resignFirstResponder(),然后becomeFirstResponder()。这将调用keyboardWillHide通知,然后keyboardWillShow通知
  2. 在其中keyboardWillHideself.view.layoutIfNeeded()没有动画的视图(和子视图-文本字段)布局。

因此,文本字段的布局是“固定的”,并且当您在keyboardWillShow文本字段中的文本中进行动画处理时,它不再“跳转”了,因为您在中进行了布局keyboardWillHide

但是,当您仅点击另一个文本字段时,仅会keyboardWillShow被调用,布局不会在文本字段中“固定”,并且在为视图设置动画时,文本会产生“跳转”动画。

这就是为什么当您单击键盘上的“下一步”时,它不会跳转,而当您单击另一个文本字段时,它会跳转。

所以我建议将其更改为:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if textField === self.loginField {
        self.passwordField.becomeFirstResponder()
        return false
    }

    return true
}

func keyboardWillShow(notification : NSNotification) {
    let keyboardInfo = notification.userInfo!
    let keyboardFrame = keyboardInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue
    let animDuration = keyboardInfo[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue!

    self.loginField.layoutIfNeeded()
    self.passwordField.layoutIfNeeded()

    if keyboardFrame.height != self.scrollViewBottom.constant {
        UIView.animateWithDuration(animDuration, animations: {
            self.scrollViewBottom.constant = keyboardFrame.height
            self.view.layoutIfNeeded()

            let offsetY = CGRectGetMaxY(self.loginButton.frame) + 10 - self.scrollView.frame.height
            if offsetY > 0 {
                self.scrollView.contentOffset = CGPointMake(0, offsetY)
            }
        })
    }
}
2020-07-07