更新 textFieldDidBeginEditing 方法中的约束会导致文本弹回
Updating constraints in textFieldDidBeginEditing method causes text to bounce
我有一个 UIView
,其中包含另一个名为 contentView
的 UIView
对象。在 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];
}];
}
这解决了我遇到的问题。
我有一个 UIView
,其中包含另一个名为 contentView
的 UIView
对象。在 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];
}];
}
这解决了我遇到的问题。