我正在将一个iOS 6.1的应用程序移植到iOS 7。我的布局中有一个UITextView
,它具有固定的宽度,但其高度基于其内容大小。在iOS 6.1中,检查contentsize.height并将其设置为textview的框架高度就足够了,但在iOS 7上不起作用。
那么,我该如何创建一个UITextView
,它具有固定的宽度,但其高度根据所显示的文本而动态变化?
注意:我是通过代码创建这些视图,而不是使用Interface Builder。
我正在将一个iOS 6.1的应用程序移植到iOS 7。我的布局中有一个UITextView
,它具有固定的宽度,但其高度基于其内容大小。在iOS 6.1中,检查contentsize.height并将其设置为textview的框架高度就足够了,但在iOS 7上不起作用。
那么,我该如何创建一个UITextView
,它具有固定的宽度,但其高度根据所显示的文本而动态变化?
注意:我是通过代码创建这些视图,而不是使用Interface Builder。
使用以下代码,您可以根据固定的宽度更改UITextView的高度(在iOS 7及以前的版本中有效):
- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
UITextView *textView = [[UITextView alloc] init];
[textView setAttributedText:text];
CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
使用此函数,您可以将NSAttributedString和固定宽度作为输入,返回所需的高度。
如果您想从特定字体的文本计算框架,则需要使用以下代码:
- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
{
CGRect frame = [text boundingRectWithSize:size
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName:font}
context:nil];
return frame.size;
}
else
{
return [text sizeWithFont:font constrainedToSize:size];
}
}
您可以在项目的prefix.pch文件中添加SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
,例如:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
你也可以用以下内容替换之前的测试SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)
:
if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])
这对我在iOS6和7上有效:
CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
self.myTextView.height = textViewSize.height;
textView.bounds.size.height
@Hexark textView.bounds.size.height
- userUITextView
使用NSLayoutManager
来布局文本:// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions. The default is NO. Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked. It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;
禁用allowsNonContiguousLayout
来修复contentSize
:
textView.layoutManager.allowsNonContiguousLayout = NO;
使用这个小函数
-(CGSize) getContentSize:(UITextView*) myTextView{
return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
我的最终解决方案是基于HotJard的,但包括文本容器顶部和底部插图,而不是使用2 * fabs(textView.contentInset.top):
- (CGFloat)textViewHeight:(UITextView *)textView
{
return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
textView.textContainerInset.top +
textView.textContainerInset.bottom);
}
+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
}else{
textView.height = textView.contentSize.height;
}
}
更新:仅用于显示文本(isEditable = NO)usedRectForTextContainer
方法返回相同的高度。 - Valerii Pavlov _textView.textContainerInset = UIEdgeInsetsZero;
_textView.textContainer.lineFragmentPadding = 0;
只是不要忘记 lineFragmentPadding
@Ana和@Blake Hamilton的解决方案使用Swift。
var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height
isScrollEnable
被设置为 false 时,它也会返回正确的 contentSize
。如果设置为false,它将返回文本视图的框架大小而非内容大小。textView.isScrollEnabled = false
,当在另一个滚动视图或带有UITableViewAutomaticDimension
的tableView单元格中时,效果完美。
NSStringDrawingUsesFontLeading
是额外的。 - user2159978(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
这对我很有帮助。 - samthui7