在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 0,0
Posted
技术标签:
【中文标题】在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 0,0【英文标题】:Using NSLayoutConstraint on UITextView resets contentSize to 0,0在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 0,0 【发布时间】:2013-04-11 22:47:33 【问题描述】:我有一个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:
中添加了一个技巧,以将 contentSize 重置为重置前的值,但这会产生一些丑陋的副作用,例如滚动位置被重置,并且视图在键入开始之前不会滚动到光标位置。
- (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;
有人知道如何完全避免这个问题吗?
【问题讨论】:
听起来你可能也有一个从超级视图顶部到顶部的约束。如果是这样,您想摆脱它,但要为文本视图设置明确的高度。 @rdelmar 为什么***约束很重要或会以任何方式影响 contentSize?在任何情况下,移除顶部约束意味着完全放弃此视图控制器的自动布局。 因为如果你有一个顶部约束,并且你将底部向上移动到顶部所在的位置,那么满足约束的唯一方法就是让高度为 0。 @rdelmar 底部被键盘的高度移动——而不是视图的顶部。 【参考方案1】:我不知道您的代码有什么问题,如果您愿意,我们可以详细处理。但作为初步建议,如果可能,不要调整 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;
];
(也许这个技巧也会以某种方式帮助您的代码。)
【讨论】:
以上是关于在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 0,0的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 带有 SpriteNodes 和 UILabel 的 NSLayout 表
在 UITableViewCell 中的 UITextView 上使用 CAGradientLayer
在 UITextView 上使用 NSLayoutConstraint 会将 contentSize 重置为 0,0