iphone - 在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 {0,0}

标签 iphone ios cocoa-touch autolayout

我有一个 UITextView,在上面我使用 NSLayoutConstraint 来躲避键盘。这是约束:

self.textViewBottomConstraint = [NSLayoutConstraint constraintWithItem:textView
                                                    attribute:NSLayoutAttributeBottom
                                                    relatedBy:NSLayoutRelationEqual
                                                       toItem:self.view
                                                    attribute:NSLayoutAttributeBottom
                                                   multiplier:1.0
                                                     constant:0.0];
[self.view addConstraint:self.textViewBottomConstraint];

当键盘显示/隐藏时,我通过将约束常量设置为键盘高度来对约束进行动画处理。但是,由于某种原因这样做会将 contentSize 重置为 {0,0},从而中断滚动。我在 handleKeyboardDidHide: 添加了一个 hack,以将 contentSize 重置为重置之前的值,但这会产生一些丑陋的副作用,例如滚动位置被重置以及 View 未滚动到光标位置直到开始输入。

- (void) handleKeyboardDidShow:(NSNotification *)notification
{
     CGFloat height = [KeyboardObserver sharedInstance].keyboardFrame.size.height;
     self.textView.constant = -height;
     [self.view layoutIfNeeded];
}

- (void) handleKeyboardDidHide:(NSNotification *)notification
{
   // for some reason, setting the bottom constraint resets the contentSize to {0,0}...
   // so let's save it before and reset it after.
   // HACK
   CGSize size = self.textView.contentSize;
   self.textView.constant = 0.0;
   [self.view layoutIfNeeded];
   self.textView.contentSize = size;
}

有人知道如何完全避免这个问题吗?

最佳答案

我不知道您的代码有什么问题,如果您愿意,我们可以详细处理该问题。但作为最初的建议,如果可能的话,不要调整 UITextView 的大小:只需更改其内容并滚动插图,如下所示:

- (void) keyboardShow: (NSNotification*) n {
    NSDictionary* d = [n userInfo];
    CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    self.tv.contentInset = UIEdgeInsetsMake(0,0,r.size.height,0);
    self.tv.scrollIndicatorInsets = UIEdgeInsetsMake(0,0,r.size.height,0);
}

即便如此,我发现您必须等到键盘隐藏动画完成才能重置这些值:

- (void) keyboardHide: (NSNotification*) n {
    NSDictionary* d = [n userInfo];
    NSNumber* curve = d[UIKeyboardAnimationCurveUserInfoKey];
    NSNumber* duration = d[UIKeyboardAnimationDurationUserInfoKey];
    [UIView animateWithDuration:duration.floatValue delay:0
                        options:curve.integerValue << 16
                     animations:
     ^{
         [self.tv setContentOffset:CGPointZero];
     } completion:^(BOOL finished) {
         self.tv.contentInset = UIEdgeInsetsZero;
         self.tv.scrollIndicatorInsets = UIEdgeInsetsZero;
     }];
}

(这个技巧可能也会以某种方式帮助您的代码。)

关于iphone - 在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 {0,0},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15960197/

相关文章:

ios - 尝试在 Xcode 中导入 Google Maps SDK 时出现编译器错误

ios - 需要在 icarousel 中拖放 View

iphone - 如何使用 Reachability 检测网络变化?

ios - 将 subview 添加到选定的表格 View 单元格

iphone - iPhone 上的同步 NSURLConnection 线程

iphone - 如何更改自定义 NSURLProtocol 的内容类型?

ios - Socket.IO - 类型 'WebSocket' 的值没有成员 'onHttpResponseHeaders'

iphone - 为 UISlider 使用字符串数组

ios - TableView Controller 没有显示 Assets 文件夹中的内容,或者根本没有显示任何内容

iphone - 使用 skpsmtpmessage 问题从 iphone 应用程序发送邮件