UITextField文本跳转iOS 9

时间:2015-10-07 08:13:40

标签: ios iphone swift swift2 ios9

上一个问题的链接: UITextField text jumps

简言之: 我有ViewControllerUITextField个元素。当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,为此我将底部空间更改为superview,因此即使显示键盘,用户也可以滚动所有内容

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有一些垃圾框架值,这里是使用下一个按钮更改第一响应者时的日志(工作正常,没有毛刺):

  

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]   2015-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]

分辨率

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

5 个答案:

答案 0 :(得分:7)

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

  1. 您正在呼叫resignFirstResponder(),然后呼叫becomeFirstResponder()。这会调用keyboardWillHide通知,然后调用keyboardWillShow通知
  2. keyboardWillHide中,您self.view.layoutIfNeeded()布局了视图(和子视图 - 文本字段)而没有动画。
  3. 因此,文本字段布局是“固定的”,当您在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)
                }
            })
        }
    }
    

答案 1 :(得分:6)

Tnx到haluzak

$wheelnumber = $_POST['wheelnumber'];

答案 2 :(得分:5)

当我试图改变第一响应者时,我遇到了同样的问题。这个问题有一个更好的解决方案。只需实现UITextField子类并在地方使用,您可以在其中设置文本字段的动画(键盘,首先响应切换等)。

@interface UITextFieldFixed : UITextField

@end

@implementation UITextFieldFixed

- (BOOL)resignFirstResponder
{
    BOOL result = [super resignFirstResponder];
    [self setNeedsLayout];
    [self layoutIfNeeded];
    return result;
}

@end

有关问题的详细信息:https://github.com/foundry/UITextFieldBug

复制并粘贴Swift3 ...

class UITextFieldFixed: UITextField {
    override func resignFirstResponder() -> Bool {
        let r = super.resignFirstResponder()
        self.setNeedsLayout()
        self.layoutIfNeeded()
        return r
    }
}

答案 3 :(得分:0)

将此代码放入键盘将显示通知,然后再进行任何动画:

UIView.performWithoutAnimation({
    self.yourTextField1.layoutIfNeeded()
    self.yourTextField2.layoutIfNeeded()
    //etc.
})

答案 4 :(得分:0)

以下是您需要编写的用于停止跳转文本的简单代码。这对我有用。

func textFieldDidEndEditing(_ textField: UITextField) { // Workaround for the jumping text bug. textField.resignFirstResponder() textField.layoutIfNeeded() }