UITextView NSAttributedString大小

我正在使用一个使用UITextView的应用程序。

UITextView应该增大或缩小以适合其文本,包括垂直和水平。 为此,我在子类中重写sizeToFit,并设置边界如下:

- (void)sizeToFit { [self setBounds:(CGRect){.size = self.attributedText.size}]; } 

问题是这个大小只是没有反映字符串的正确大小,因为UITextView会剪切文本。 我将边缘插入设置为零,所以这不应该是一个问题吧?

在这一点上,我认为这是NSAttributedString的size属性的一个错误,但是如果我使用boundingRectWithSize,则会发生同样的事情:options:context:

 [self setBounds:(CGRect){.size = [self.attributedText boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:0 context:nil].size}]; 

因此,无论代码是什么,NSAttributedString的布局计算都无法与UITextView的布局计算很好地协作。

这是演示该问题的示例项目 。

欢迎任何想法!

编辑:我还应该指出以下不起作用:

 - (void)sizeToFit { [self setBounds:(CGRect){.size = [self sizeThatFits:self.attributedText.size]}]; } 

虽然不完美,但我最终使用:

 - (void)sizeToFit { CGSize textSize = self.attributedText.size; CGSize viewSize = CGSizeMake(textSize.width + self.firstCharacterOrigin.x * 2, textSize.height + self.firstCharacterOrigin.y * 2); [self setBounds:(CGRect){.size = [self sizeThatFits:viewSize]}]; } - (CGPoint)firstCharacterOrigin { if (!self.text.length) return CGPointZero; UITextRange * range = [self textRangeFromPosition:[self positionFromPosition:self.beginningOfDocument offset:0] toPosition:[self positionFromPosition:self.beginningOfDocument offset:1]]; return [self firstRectForRange:range].origin; } 

我认为你是对的 – 我无法得到-[NSAttributedString boundingRectWithSize:options:context: ]返回一个适用于所有字体大小的值…

我确实得到了一个UILabel来正确resize并绘制属性字符串:

  • 将文本视图类更改为UILabel
  • 在标签上使用-setAttributedText:
  • set label.numberOfLines = 0 (multiline)
  • in -layoutSubviews你的标签的-layoutSubviews视图调用 – [label sizeThatFits:]来获得标签的正确大小….

为我工作……

编辑:这是我的ViewController.m文件:

 @interface View : UIView @property ( nonatomic, strong ) UITextView * textView ; @property ( nonatomic, strong ) UISlider * fontSizeSlider ; @end @implementation View -(void)layoutSubviews { CGRect bounds = self.bounds ; self.textView.layer.anchorPoint = (CGPoint){ 0.0f, 0.5f } ; self.textView.layer.position = (CGPoint){ CGRectGetMinX( bounds ), CGRectGetMidY( bounds ) } ; self.textView.bounds = (CGRect){ .size = [ self.textView sizeThatFits:bounds.size ] } ; self.fontSizeSlider.frame = CGRectMake(5, CGRectGetMaxY(bounds) - 30, bounds.size.width - 10, 25) ; } @end @interface ViewController () @end @implementation ViewController -(void)loadView { self.view = [[ View alloc ] initWithFrame:CGRectZero ] ; } - (void)viewDidLoad { [super viewDidLoad]; NSMutableAttributedString * aString = [[ NSMutableAttributedString alloc ] initWithString:@"Some test text in a scaling text view" ] ; NSDictionary * attributes = @{ NSForegroundColorAttributeName : [ UIColor redColor ] } ; [ aString setAttributes:attributes range:(NSRange){ 5, 4 } ] ; textView = [[UITextView alloc] initWithFrame:CGRectZero]; [textView setAttributedText:aString ]; [textView setFont:[UIFont systemFontOfSize:18]]; [textView setCenter:CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds))]; ((View*)self.view).textView = textView ; [self.view addSubview:textView]; [textView release]; UISlider * fontSizeSlider = [[UISlider alloc] initWithFrame:CGRectMake(5, CGRectGetMaxY(self.view.bounds) - 30, self.view.bounds.size.width - 10, 25)]; [fontSizeSlider addTarget:self action:@selector(fontSizeSliderDidChange:) forControlEvents:UIControlEventValueChanged]; [fontSizeSlider setMinimumValue:5]; [fontSizeSlider setMaximumValue:100]; [fontSizeSlider setValue:textView.font.pointSize]; ((View*)self.view).fontSizeSlider = fontSizeSlider ; [self.view addSubview:fontSizeSlider]; [fontSizeSlider release]; } - (void)fontSizeSliderDidChange:(UISlider *)sender { [ textView setFont:[textView.font fontWithSize:sender.value]]; [ self.view setNeedsLayout ] ; } @end 

以上的汤姆欧文解决方案的swift 3解决方案:

 extension UITextView { func sizeToFitAttributedString() { let textSize = self.attributedText.size() let viewSize = CGSize(width: textSize.width + self.firstCharacterOrigin.x * 2, height: textSize.height + self.firstCharacterOrigin.y * 2) self.bounds.size = self.sizeThatFits(viewSize) } private var firstCharacterOrigin: CGPoint { if self.text.lengthOfBytes(using: .utf8) == 0 { return .zero } let range = self.textRange(from: self.position(from: self.beginningOfDocument, offset: 0)!, to: self.position(from: self.beginningOfDocument, offset: 1)!) return self.firstRect(for: range!).origin } }