更新 textFieldDidBeginEditing 方法中的约束会导致文本弹回

Updating constraints in textFieldDidBeginEditing method causes text to bounce

我有一个 UIView,其中包含另一个名为 contentViewUIView 对象。在 contentView 中,我有几个 UITextField 对象。为了使当前编辑 UITextField 始终可见并且不会被键盘隐藏,我正在更改 textFieldDidBeginEditing: 方法内对 contentView 的约束。这意味着 contentView 在父 UIView 内上下滑动,并保持相关 UITextField 可见。这部分工作正常,但这里有一个代码片段:

- (void)textFieldDidBeginEditing:(UITextField *)textField
    //offset calculation removed for clarity
    NSInteger offset = ....

    self.contentViewTopConstraint.constant = -offset;
    self.contentViewBottomConstraint.constant = offset;
    [self.view setNeedsUpdateConstraints];

    [UIView animateWithDuration:0.3 animations:^{
        [self.view layoutIfNeeded];
    }];
}

我注意到,如果我在第一个 UITextField 中键入一些文本,然后点击第二个 UITextField,第一个 UITextField 中的文本会向上跳然后返回再次下降。如果我在上面的代码片段中禁用动画,这种行为就会消失。所以我的猜测是,当编辑 UITextField 时,设置了一些其他约束,然后随着焦点从 UITextField 移开而改变。当我告诉视图以动画方式更新它的约束时,这会导致文本四处移动。

有什么方法可以避免这种情况,但仍然保持上下移动 contentView 的动画?

编辑: 在我更新任何约束之前添加一个额外的 [self.view layoutIfNeeded] 调用解决了这个问题。我仍然不确定可能发生了什么,或者为什么会修复它。有人有任何见解吗?

我不确定你的这段代码有什么问题,我需要更多代码才能告诉你那段代码有什么问题,但你可以使用这段代码,它会为你工作

-(void)addObservers
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardIsShowing:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardIsHiding:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

-(void)removeObservers
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardIsShowing:(NSNotification*)notification
{

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
    [UIView setAnimationBeginsFromCurrentState:YES];

    int scaleFactor = 0;
    if([oldPasswrdField isFirstResponder])
        scaleFactor = 20;
    else if([newPasswrdField isFirstResponder])
        scaleFactor = 76;
    else if([confirmPasswrdField isFirstResponder])
        scaleFactor = 132;

    self.contentView.frame = CGRectMake(self.contentView.frame.origin.x, self.view.frame.origin.y-scaleFactor,self.contentView.frame.size.width, self.contentView.frame.size.height);


    [UIView commitAnimations];

}

- (void)keyboardIsHiding:(NSNotification*)notification
{

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]];
    [UIView setAnimationBeginsFromCurrentState:YES];


    self.contentView.frame = CGRectMake(self.contentView.frame.origin.x, 0, self.contentView.frame.size.width, self.contentView.frame.size.height);

    //self.view.frame = frame;


    [UIView commitAnimations];

}

您在 keyboardIsShowing 方法中看到了 scalefactor。需要根据您正在编辑的文本字段进行设置。如果可以,您可以只获取当前响应的文本字段并将其取为 origin.y 并据此设置比例因子。另外,在viewDidAppear中调用addObservers,在viewDidDisappear中调用removeObservers。或者根据您的需要,但不要忘记同时调用它们一次。

编辑:告诉我这是否适合您,或者如果您需要进一步的帮助,我们很乐意提供帮助。

从那以后,我了解到为约束设置动画的正确方法是这样的:

- (void)textFieldDidBeginEditing:(UITextField *)textField
    //offset calculation removed for clarity
    NSInteger offset = ....

    [self.view layoutIfNeeded];
    self.contentViewTopConstraint.constant = -offset;
    self.contentViewBottomConstraint.constant = offset;

    [UIView animateWithDuration:0.3 animations:^{
        [self.view layoutIfNeeded];
    }];
}

这解决了我遇到的问题。