如何使用Autolayout动画调整内容滚动时调整UITextView的底部约束的动画

Cli*_*itt 6 animation objective-c uitextview ios autolayout

背景

我正在研究一个快速而肮脏的笔记应用,纯粹是为了尝试理解自动布局.因此,我正在寻找针对此问题的特定于自动布局的解决方案.

我很确定我的术语和对这个主题的理解可能在某些地方是不正确的,所以如果我通过无知而错误地忽略或省略信息,否则我将非常乐意用更好的细节来更新这个问题.

简短问题摘要

  • 这个应用程序是一个简单的笔记应用 在注释的详细视图中,有两个文本输入视图,一个UITextField和一个UITextView.
  • 目标是使用autolayout在编辑时为UITextView设置高度变化(为键盘腾出空间),然后在编辑完成后将UITextView设置为原始大小.
  • 我所使用的动画代码有效,但是当UITextView滚动到文本底部附近时,从"编辑"大小到"非编辑"大小的动画在动画中显示不正确.(动画的最终结果是正确的.)
  • 如果解决方案有一个共同的模式,我愿意采用替代的"正确"方法.但是,我正在寻找一种自动布局解决方案,我相信这意味着避免直接修改视图的帧.(可能是错的.)

细节和代码

有关此问题的简短视频,请访问:http:
//pile.cliffpruitt.com/m/constraint_problem.mp4

这是执行动画的代码:

// self.bodyFieldConstraintBottom refers to an outlet referencing the UITextView's bottom constraint

// This animation occurrs when the text view is tapped
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    [self enterEditingMode];

    [UIView animateWithDuration:2.35
                     animations:^{
                         NSLayoutConstraint *bottom_constraint = self.bodyFieldConstraintBottom;
                         bottom_constraint.constant = 216;
                         [self.view layoutIfNeeded];
                     }];

    return YES;
}

// This animation occurrs when editing ends and the text field size is restored
- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
    [self exitEditingMode];

    [UIView animateWithDuration:2.35
                     animations:^{
                         NSLayoutConstraint *bottom_constraint = self.bodyFieldConstraintBottom;
                         bottom_constraint.constant = 20;
                         [self.view layoutIfNeeded];
                     }];

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

完整的项目源(在所有它的凌乱的荣耀)可以在这里下载:http:
//pile.cliffpruitt.com/dl/LittleNotebooks.zip

附加评论

我对可可术语的理解不是最好的,所以我很难让谷歌搜索和文档搜索有效.我对这个问题的最佳猜测(基于以慢速观察动画)是因为它与某个滚动偏移有关,因为除非文本滚动超过某一点,否则问题本身并未表现出来.

我已阅读了不少SO问题/答案,包括:

问题是这些答案要么不起作用([self.bodyField setContentInset:UIEdgeInsetsMake(0,0,216,0)];似乎没有效果)或者似乎依赖于设置我相信的UIText视图的框架在使用自动布局时不应该这样做.

最后一面注意

我已经在这里休息了大约4天,所以我对所有阅读和尝试过的理解和记忆实际上都不如我开始时那么清晰.我希望我能够很好地解释这个问题.

编辑:

我注意到这段代码实际上有点接近所需的结果:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    [self enterEditingMode];


    [UIView animateWithDuration:2.35
                     animations:^{
                         [self.bodyField setContentInset:UIEdgeInsetsMake(0, 0, 216, 0)];
                         [self.view layoutIfNeeded];
                     }];

    return YES;
}

- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
    [self exitEditingMode];

    [UIView animateWithDuration:2.35
                     animations:^{
                         [self.bodyField setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
                         [self.view layoutIfNeeded];
                     }];

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

这个版本的问题是滚动指示器向下滚过文本内容的可见区域,这意味着它在键盘后面"丢失".此外,它无法帮助我理解动画UITextView(UIScrollView?)底部约束的正确方法.

Bar*_*nas 0

这个问题看起来很奇怪,我真的不确定主要问题是什么,但我发现为了获得最佳结果,您应该[self.view setNeedsUpdateConstraints];在动画视图之前调用。

当键盘出现时我的动画视图示例代码:

-(void)keyboardWillShow:(NSNotification *)notification {
    CGSize kbSize = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //BH: iOS7 is messed up
    CGFloat keyboardHeight = kbSize.width;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        keyboardHeight = kbSize.height;
    }

    self.centerYConstraint.constant = keyboardHeight;
    [self.view setNeedsUpdateConstraints];

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

    [UIView commitAnimations];
}
Run Code Online (Sandbox Code Playgroud)

我正在使用提交动画来为视图设置动画,就像animationCurveiOS 为键盘设置动画一样,因此视图会根据键盘以 1 比 1 的比例移动。另外,请注意 iOS8 与 iOS7 的 if 声明,其中 Apple 最终修复了窗口大小。