如何使用自动布局动画调整内容滚动时调整文本视图的底部约束的动画

时间:2014-08-06 17:56:54

标签: ios objective-c animation uitextview 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;
}

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

其他评论

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

我已经阅读了很多问题/答案,包括:

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

最后一面注意

我已经在这里休息了大约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;
}

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

1 个答案:

答案 0 :(得分: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];
}

我正在使用提交动画来设置与animationCurve相同的视图动画,因为iOS是动画键盘,因此视图相应地向键盘移动1到1。另外,请注意iOS8与iOS7的声明,其中Apple最终修改了窗口大小。