我如何大小一个UITextView到它的内容?

是否有一种好方法来调整UITextView的大小以符合其内容?例如,我有一个包含一行文本的UITextView:

"Hello world"

然后我添加了另一行文本:

"Goodbye world"

在Cocoa Touch中是否有一个好方法来获得rect,它将保存文本视图中的所有行,以便我可以相应地调整父视图?

另一个例子是,查看Calendar应用程序中用于事件的notes字段——注意单元格(以及它包含的UITextView)如何展开以容纳notes字符串中的所有文本行。

417383 次浏览

你试过[textView sizeThatFits:textView.bounds]吗?

编辑:sizeThatFits返回大小,但并不实际调整组件的大小。我不确定这是否是你想要的,或者[textView sizeToFit]是你想要的。无论哪种情况,我不知道它是否完全适合你想要的内容,但这是第一件要尝试的事情。

另一个方法是使用NSString方法查找特定字符串将占用的大小:

# EYZ0

它返回符合给定字符串和给定字体的矩形的大小。传入一个具有所需宽度和最大高度的大小,然后您可以查看返回的适合文本的高度。还有一个版本允许您指定换行模式。

然后,您可以使用返回的大小来更改视图的大小以适应。

结合迈克·麦克马斯特的回答,你可能会想这样做:

[myTextView setDelegate: self];


...


- (void)textViewDidChange:(UITextView *)textView {
if (myTextView == textView) {
// it changed.  Do resizing here.
}
}

根据我有限的经验,

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

不尊重换行符,所以你可以用比实际需要的更短的CGSize结束。

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

看起来很尊重换行符。

此外,文本实际上并没有在UITextView的顶部渲染。在我的代码中,我将UITextView的新高度设置为比sizeOfFont方法返回的高度大24个像素。

希望这能有所帮助:

- (void)textViewDidChange:(UITextView *)textView {
CGSize textSize = textview.contentSize;
if (textSize != textView.frame.size)
textView.frame.size = textSize;
}

这在ios7或更高版本上不再适用

实际上,有一种非常简单的方法可以将UITextView的大小调整到内容的正确高度。可以使用UITextView contentSize

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

需要注意的一点是,正确的contentSize只有可用,UITextView已经和addSubview一起添加到视图中。在此之前,它等于frame.size

如果开启自动布局,这将不起作用。对于自动布局,一般的方法是使用sizeThatFits方法并在高度限制上更新constant值。

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraint是一个布局约束,通常通过IBOutlet将属性链接到故事板中创建的高度约束来设置。


再加上这个惊人的答案,2014年,如果你:

[self.textView sizeToFit];

只有iPhone6 +在行为上有区别:

enter image description here

只有6+(不是5s或6),它确实添加了“一个更多的空白行”到UITextView。“RL解决方案”完美地解决了这个问题:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

它修复了6+上的“额外行”问题。

我找到了一种方法,根据里面的文本调整文本字段的高度,并根据文本字段的高度在下面安排一个标签!这是代码。

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;


[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;


UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];

如果有任何其他得到这里,这个解决方案为我工作,1“Ronnie Liew”+4“user63934”(我的文本从web服务到达): 注意1000(在我的情况下没有什么可以这么大)

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];


NSString *dealDescription = [client objectForKey:@"description"];


//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];


CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);


UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];


dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];


//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

那就是……干杯

当我需要在UITextView中制作适合特定区域的文本时,这工作得很好:

// The text must already be added to the subview, or contentviewsize will be wrong.


- (void) reduceFontToFit: (UITextView *)tv {
UIFont *font = tv.font;
double pointSize = font.pointSize;


while (tv.contentSize.height > tv.frame.size.height && pointSize > 7.0) {
pointSize -= 1.0;
UIFont *newFont = [UIFont fontWithName:font.fontName size:pointSize];
tv.font = newFont;
}
if (pointSize != font.pointSize)
NSLog(@"font down to %.1f from %.1f", pointSize, tv.font.pointSize);
}

如果手边没有UITextView(例如,您正在调整表格视图单元格的大小),则必须通过测量字符串来计算大小,然后在UITextView的每一侧计算8 pt的填充。例如,如果你知道你的文本视图的期望宽度,并想要计算出相应的高度:

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;


CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

在这里,每个8都是四个填充边中的一个,100000只是一个非常大的最大尺寸。

在实践中,你可能想要添加一个额外的font.leading到高度;这将在文本下方添加一个空行,如果文本视图正下方有视觉上沉重的控件,这可能会看起来更好。

我发现的最好的方法是根据文本的大小来调整UITextView的高度。

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

或者你可以使用

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];

在iOS6中,你可以在设置文本后立即检查UITextView的contentSize属性。在iOS7中,这将不再有效。如果你想在iOS7中恢复这个行为,把下面的代码放在UITextView的子类中。

- (void)setText:(NSString *)text
{
[super setText:text];


if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
UIEdgeInsets inset = self.textContainerInset;
self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
}
}

对于iOS 7.0,不要将frame.size.height设置为contentSize.height(目前没有任何作用),而是使用[textView sizeToFit]

看到# EYZ0。

这适用于iOS 6.1和iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
}

或在Swift(适用于Swift 4.1在iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

如果你想要支持iOS 6.1,那么你还应该:

textview.scrollEnabled = NO;

这个方法似乎适用于ios7

 // Code from apple developer forum - @Steve Krulewitz, @Mark Marszal, @Eric Silverberg
- (CGFloat)measureHeight
{
if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)])
{
CGRect frame = internalTextView.bounds;
CGSize fudgeFactor;
// The padding added around the text on iOS6 and iOS7 is different.
fudgeFactor = CGSizeMake(10.0, 16.0);


frame.size.height -= fudgeFactor.height;
frame.size.width -= fudgeFactor.width;


NSMutableAttributedString* textToMeasure;
if(internalTextView.attributedText && internalTextView.attributedText.length > 0){
textToMeasure = [[NSMutableAttributedString alloc] initWithAttributedString:internalTextView.attributedText];
}
else{
textToMeasure = [[NSMutableAttributedString alloc] initWithString:internalTextView.text];
[textToMeasure addAttribute:NSFontAttributeName value:internalTextView.font range:NSMakeRange(0, textToMeasure.length)];
}


if ([textToMeasure.string hasSuffix:@"\n"])
{
[textToMeasure appendAttributedString:[[NSAttributedString alloc] initWithString:@"-" attributes:@{NSFontAttributeName: internalTextView.font}]];
}


// NSAttributedString class method: boundingRectWithSize:options:context is
// available only on ios7.0 sdk.
CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];


return CGRectGetHeight(size) + fudgeFactor.height;
}
else
{
return self.internalTextView.contentSize.height;
}
}

我会在页面底部发布正确的解决方案,以防有人勇敢(或绝望)读到这一点。

这里是那些不想阅读所有文本的人的gitHub回购:resizableTextView

简洁优雅的解决方案。

我认为,所有与约束相关的代码都应该去updateConstraints方法。所以,让我们创建自己的ResizableTextView

我们在这里遇到的第一个问题是在viewDidLoad方法之前不知道真实的内容大小。我们可以根据字体大小、换行等进行计算。但我们需要稳健的解决方案,所以我们会:

# EYZ0

所以现在我们知道真正的contentSize,无论我们在哪里:在viewDidLoad之前或之后。现在在textView上添加高度约束(通过storyboard或代码,无论如何)。我们将用contentSize.height调整这个值:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = contentSize.height;
*stop = YES;
}
}];

最后要做的事情是告诉超类updateConstraints

[super updateConstraints];

现在我们的类看起来是这样的:

ResizableTextView.m

- (void) updateConstraints {
CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];


[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = contentSize.height;
*stop = YES;
}
}];


[super updateConstraints];
}

又漂亮又干净,对吧?并且您不必在控制器!

< >强劲但等等! 没有动画!< / >强

您可以轻松地进行动画更改,使textView平滑地伸展。这里有一个例子:

    [self.view layoutIfNeeded];
// do your own text change here.
self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
[self.infoTextView setNeedsUpdateConstraints];
[self.infoTextView updateConstraintsIfNeeded];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
[self.view layoutIfNeeded];
} completion:nil];

更新

你需要做的关键事情是关闭UITextView中的滚动。

myTextView.scrollEnabled = @NO

原来的答案

要在UITableViewCell中动态调整UITextView的大小,我发现以下组合在Xcode 6和iOS 8 SDK中有效:

  • 添加UITextViewUITableViewCell,并将其约束到两侧

  • UITextViewscrollEnabled属性设置为NO。在启用滚动的情况下,UITextView的框架独立于其内容大小,但在禁用滚动的情况下,两者之间存在关联。

  • 如果你的表使用原始的默认行高44,那么它会自动计算行高,但如果你改变了默认的行高,你可能需要手动在viewDidLoad中打开自动计算行高:

     tableView.estimatedRowHeight = 150;
    tableView.rowHeight = UITableViewAutomaticDimension;
    

对于只读的动态调整UITextViews大小,就是这样。如果你允许用户在UITextView中编辑文本,你还需要:

  • 实现UITextViewDelegate协议的textViewDidChange:方法,并告诉tableView在每次编辑文本时重新绘制自己:

     - (void)textViewDidChange:(UITextView *)textView;
    {
    [tableView beginUpdates];
    [tableView endUpdates];
    }
    
  • 不要忘记在某个地方设置UITextView委托,要么在Storyboard,要么在tableView:cellForRowAtIndexPath:

对于那些想要textview实际移动和保持底线位置

CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;


if(frame.size.height > textView.frame.size.height){
CGFloat diff = frame.size.height - textView.frame.size.height;
textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
CGFloat diff = textView.frame.size.height - frame.size.height;
textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}
不知道为什么人们总是把事情复杂化: 这里是:

- (void)textViewDidChange:(UITextView *)textView{ CGRect frame = textView.frame;
CGFloat height = [self measureHeightOfUITextView:textView];
CGFloat insets = textView.textContainerInset.top + textView.textContainerInset.bottom;
height += insets;
frame.size.height = height;


if(frame.size.height > textView.frame.size.height){
CGFloat diff = frame.size.height - textView.frame.size.height;
textView.frame = CGRectMake(5, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
CGFloat diff = textView.frame.size.height - frame.size.height;
textView.frame = CGRectMake(5, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}
[textView setNeedsDisplay];
}

伙计们,使用自动布局和你的尺寸不适合,然后请检查你的宽度限制一次。如果您错过了宽度约束,那么高度将是准确的。

不需要使用任何其他API。只要一行字就能解决所有问题。

[_textView sizeToFit];

在这里,我只关心高度,保持宽度固定,错过了我的TextView在故事板的宽度约束。

这是为了显示来自服务的动态内容。

希望这能有所帮助。

这是@jhibberd的快速版本

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
cell.msgText.text = self.items[indexPath.row]
var fixedWidth:CGFloat = cell.msgText.frame.size.width
var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
var newSize:CGSize = cell.msgText.sizeThatFits(size)
var newFrame:CGRect = cell.msgText.frame;
newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
cell.msgText.frame = newFrame
cell.msgText.frame.size = newSize
return cell

唯一可以工作的代码是使用“SizeToFit”的jhibberd answer上面,但实际上它不会捡起,除非你在在ViewDidAppear中调用它或将其连接到UITextView text changed event。

基于Nikita Took的回答,我想出了以下解决方案,适用于iOS 8的自动布局:

    descriptionTxt.scrollEnabled = false
descriptionTxt.text = yourText


var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
for c in descriptionTxt.constraints() {
if c.isKindOfClass(NSLayoutConstraint) {
var constraint = c as! NSLayoutConstraint
if constraint.firstAttribute == NSLayoutAttribute.Height {
constraint.constant = contentSize.height
break
}
}
}
< p >迅速回答: 下面的代码计算textView的高度。< / p >
                let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX)
let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin
let attribute = [NSFontAttributeName: textView.font!]
let str = NSString(string: message)
let labelBounds = str.boundingRectWithSize(maximumLabelSize,
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: attribute,
context: nil)
let myTextHeight = CGFloat(ceilf(Float(labelBounds.height)))

现在你可以设置你的textView的高度为myTextHeight

从iOS 8开始,可以使用UITableView的自动布局功能来自动调整UITextView的大小,而不需要任何自定义代码。我已经在github中放置了一个项目来演示这一点,但这里是关键:

  1. UITextView必须禁用滚动,这可以通过编程或通过接口构建器来实现。如果启用滚动,它将不会调整大小,因为滚动可以让您查看较大的内容。
  2. 在UITableViewController的viewDidLoad中,你必须为estimatedRowHeight设置一个值,然后将rowHeight设置为UITableViewAutomaticDimension

- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = self.tableView.rowHeight;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. 项目部署目标必须是iOS 8或更高版本。

迅速:

textView.sizeToFit()
问一个UITextView最简单的方法是调用-sizeToFitit应该也与scrollingEnabled = YES,之后检查高度和添加高度约束的文本视图具有相同的值 注意,UITexView包含insets,这意味着你不能询问字符串对象它想要使用多少空间,因为这只是文本的边界矩形 所有使用-sizeToFit的人都遇到了错误的大小,这可能是由于文本视图还没有布局到界面大小 当你使用size类和UITableView时,这种情况总是发生,第一次在- tableView:cellForRowAtIndexPath:中创建单元格时,它的大小是任意-任意配置的,如果你刚刚计算你的值,文本视图的宽度将与预期的不同,这将会破坏所有的大小 为了克服这个问题,我发现覆盖单元格的-layoutSubviews方法来重新计算textview高度是有用的

具备以下条件就足够了:

  1. 只要记住将启用滚动设置为没有UITextView:

enter image description here

  1. 正确设置自动布局约束。

您甚至可以使用UITableViewAutomaticDimension

如果你正在使用滚动视图和内容视图,你想增加高度取决于TextView的内容高度,那么这段代码将帮助你。

希望这能有所帮助,它在iOS9.2中工作得很完美

当然,设置textview.scrollEnabled = NO;

-(void)adjustHeightOfTextView
{
//this pieces of code will helps to adjust the height of the uitextview View W.R.T content
//This block of code work will calculate the height of the textview text content height and calculate the height for the whole content of the view to be displayed.Height --> 400 is fixed,it will change if you change anything in the storybord.




CGSize textViewSize = [self.textview sizeThatFits:CGSizeMake(self.view.frame.size.width, self.view.frame.size.height)];//calulcate the content width and height


float textviewContentheight =textViewSize.height;
self.scrollview.contentSize = CGSizeMake(self.textview.frame.size.width,textviewContentheight + 400);//height value is passed
self.scrollview.frame =CGRectMake(self.scrollview.frame.origin.x, self.scrollview.frame.origin.y, self.scrollview.frame.size.width, textviewContentheight+400);


CGRect Frame = self.contentview.frame;
Frame.size.height = textviewContentheight + 400;
[self.contentview setFrame:Frame];


self.textview.frame =CGRectMake(self.textview.frame.origin.x, self.textview.frame.origin.y, self.textview.frame.size.width, textviewContentheight);
[ self.textview setContentSize:CGSizeMake( self.textview.frame.size.width,textviewContentheight)];
self.contenview_heightConstraint.constant =


self.scrollview.bounds.size.height;
NSLog(@"%f",self.contenview_heightConstraint.constant);
}

我们可以用约束来做。

  1. 为UITextView设置高度约束。 李# EYZ0 < / >

2.为高度限制创建IBOutlet。

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3.不要忘记为你的textview设置委托。

4.

-(void)textViewDidChange:(UITextView *)textView
{
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
[UIView animateWithDuration:0.2 animations:^{
_txtheightconstraints.constant=newFrame.size.height;
}];


}

然后像这样更新你的约束:

非常容易工作的解决方案使用代码和故事板。

通过代码

textView.scrollEnabled = false

通过故事板

取消选中滚动使

enter image description here

除此之外什么都不用做。

我回顾了所有的答案,所有都保持固定的宽度和调整只有高度。如果你想调整宽度,你可以很容易地使用这个方法:

当配置文本视图时,将滚动设置为禁用

textView.isScrollEnabled = false

然后在委托方法func textViewDidChange(_ textView: UITextView)中添加以下代码:

func textViewDidChange(_ textView: UITextView) {
let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}

输出:

enter image description here

enter image description here

如果你需要在staticTableView中动态调整textViewtableViewCell的大小,这里是答案

[# EYZ0

在ios 11上非常有效 我在一个单元格中工作,就像一个带气泡的聊天单元格

let content = UITextView(frame: CGRect(x: 4, y: 4, width: 0, height: 0))
content.text = "what ever short or long text you wanna try"
content.textAlignment = NSTextAlignment.left
content.font = UIFont.systemFont(ofSize: 13)
let spaceAvailable = 200 //My cell is fancy I have to calculate it...
let newSize = content.sizeThatFits(CGSize(width: CGFloat(spaceAvailable), height: CGFloat.greatestFiniteMagnitude))
content.isEditable = false
content.dataDetectorTypes = UIDataDetectorTypes.all
content.isScrollEnabled = false
content.backgroundColor = UIColor.clear
bkgView.addSubview(content)

以下是步骤

解决方案适用于所有版本的iOS。Swift 3.0及以上版本。

  1. UITextView添加到View。我用代码添加它,你可以通过界面生成器添加。
  2. 添加约束。我在代码中添加约束,你也可以在接口生成器中这样做。
  3. 使用UITextViewDelegate方法func textViewDidChange(_ textView: UITextView)来调整TextView的大小

# EYZ0

    <李> < pre > <代码> / / 1。在ViewDidLoad中添加UITextView textView = UITextView() textView.frame = CGRect(x: 0, y: 0,宽:200,高:100) textView。backgroundColor = .lightGray textView。text = "这是一些默认文本。" / / 2。添加约束 textView。translatesAutoresizingMaskIntoConstraints = false [ textView.bottomAnchor。约束(等于:view.safeAreaLayoutGuide.bottomAnchor), textView.leadingAnchor。约束(等于:view.leadingAnchor), textView.trailingAnchor。约束(等于:view.trailingAnchor), textView.heightAnchor。约束(equalToConstant: 50) textView.widthAnchor。约束(equalToConstant: 30) ]。forEach{$ 0。isActive = true} textView。font = UIFont。preferredFont (forTextStyle .headline): textView.delegate = self textView。isScrollEnabled = false textViewDidChange (textView) / / 3。实现委托方法。 func textViewDidChange(_ textView: UITextView) { let size = CGSize(width: view.frame.width, height: .infinity) let estimatedSize = textView.sizeThatFits(size) textView.constraints.forEach{(约束)在 如果约束。firstAttribute == .height { print("Height: ", estimatedSize.height) 约束。常量= estimatedSize.height } } } < /代码> < / pre > < /李>

用键值观察(KVO)很简单,只需创建UITextView的子类,然后做:

private func setup() { // Called from init or somewhere


fitToContentObservations = [
textView.observe(\.contentSize) { _, _ in
self.invalidateIntrinsicContentSize()
},
// For some reason the content offset sometimes is non zero even though the frame is the same size as the content size.
textView.observe(\.contentOffset) { _, _ in
if self.contentOffset != .zero { // Need to check this to stop infinite loop
self.contentOffset = .zero
}
}
]
}
public override var intrinsicContentSize: CGSize {
return contentSize
}

如果你不想子类化,你可以尝试在contentSize观察者中做textView.bounds = textView.contentSize

这工作很好,斯威夫特5在情况下,你想适合你的TextView一旦用户在飞行中写文本。

只需实现UITextViewDelegate:

func textViewDidChange(_ textView: UITextView) {
let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: newSize.width, height: newSize.height)
}

使用UITextViewDelegate是最简单的方法:

func textViewDidChange(_ textView: UITextView) {
textView.sizeToFit()
textviewHeight.constant = textView.contentSize.height
}

对我来说最简单的解决方案是在Storyboard的textView上放一个高度约束,然后将textView和高度约束连接到代码:

@IBOutlet var myAwesomeTextView: UITextView!
@IBOutlet var myAwesomeTextViewHeight: NSLayoutConstraint!

然后在设置文本和段落样式后,在在viewDidAppear中添加这个:

self.myAwesomeTextViewHeight.constant = self.myAwesomeTextView.contentSize.height

一些注意事项:

  1. 与其他解决方案相反,为了使其工作,使用isScrollEnabled必须设置为true
  2. 在我的例子中,我在代码中设置自定义属性的字体,因此我必须在viewDidAppear中设置高度(在此之前它不会正常工作)。如果你没有在代码中更改任何文本属性,你应该能够在viewDidLoad或设置文本后的任何地方设置高度。

看起来这个家伙为NSTextView找到了答案,他的答案也适用于iOS。事实证明,intrinsicContentSize并不与布局管理器同步。如果一个布局发生在intrinsicContentSize之后,你可能会有一个差异。

他有一个简单的解决办法。

NSTextView在NSOutlineView与IntrinsicContentSize设置错误的高度