如何为UITextView设置最大高度和固定宽度并强制省略,而不是在发生溢出时滚动?

时间:2014-03-23 18:07:19

标签: ios iphone ios7 uitextview nsattributedstring

这是我的目标:

  1. 我想使用UITextView而不是UILabel,因为我希望用户能够选择文本和复制。
  2. 我希望UITextView最高可达60点。
  3. 我希望UITextView的固定宽度为300点。
  4. 我想让UITextView在单词上换行。
  5. 让我们说,基于我给它提供的属性文本字符串,它需要3行才能达到60点最大高度。因此,如果我输入UITextView 6行的属性文本,我希望UITextView最大值为60点并显示3行后跟省略号(例如......)。
  6. 我不希望文本视图可以滚动。
  7. 如果我将UITextView作为属性文本提供给单个单词,例如" Hello",我希望UITextView仍然具有300点的固定宽度,但动态高度可以缩小到它的小到对于此示例中的单行文本,可以是大约20个点。
  8. 我希望UITextView的内部填充为零。
  9. 有什么想法吗?

3 个答案:

答案 0 :(得分:1)

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
{
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:text];
    CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

- (void)viewDidLoad
{
    // Invoke super
    [super viewDidLoad];

    // Get text of unknown length
    NSMutableAttributedString *myAttributedString = [[NSMutableAttributedString alloc] initWithString:@"String of unknown length here..." attributes:@{NSForegroundColorAttributeName : [UIColor redColor]}];

    // Get ellipsis w/ matching attributes
    NSDictionary *endCharAttributes = [myAttributedString attributesAtIndex:myAttributedString.length - 1 effectiveRange:NULL];
    NSAttributedString *ellipsis = [[NSAttributedString alloc] initWithString:@"..." attributes:endCharAttributes];

    // Define size constraints
    CGFloat maxHeight = 60;
    CGFloat fixedWidth = 300;

    // Get starting height
    CGFloat textViewHeight = [self textViewHeightForAttributedText:myAttributedString andWidth:fixedWidth];

    // Reduce string size and add ellipsis until we fit within our height constraint
    while (textViewHeight > maxHeight)
    {
        NSLog(@"%f", textViewHeight);
        NSRange substringRange = {0, myAttributedString.length - 6}; // Reducing by 6 works for my app (strings are never huge)
        myAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[myAttributedString attributedSubstringFromRange:substringRange]];
        [myAttributedString appendAttributedString:ellipsis];
        NSLog(@"myAttributedString = %@", myAttributedString);
        textViewHeight = [self textViewHeightForAttributedText:myAttributedString andWidth:fixedWidth];
    }

    // Init and config UITextView
    UITextView *textView = [[UITextView alloc] init];
    textView.attributedText = myAttributedString;
    textView.frame = CGRectMake(0, 0, fixedWidth, textViewHeight);
    [self.view addSubview:textView];
}

有更优雅的解决方案吗?发布吧!

更新:您可以通过添加帮助程序类并实现以下类方法来提高- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width的性能:

// Private, gets us to alloc init calculation view one time for life of application
+ (UITextView *)calculationView
{
    static UITextView *_calculationView;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _calculationView = [[UITextView alloc] init];
    });
    return _calculationView;
}

// Public, app calls this a lot
+ (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width usingUIEdgeInset:(UIEdgeInsets)edgeInsets
{
    [self calculationView].textContainerInset = edgeInsets;
    [self calculationView].attributedText = text;
    CGSize size = [[self calculationView] sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

答案 1 :(得分:0)

您是否考虑过继承UILabel并添加选择和复制文本的功能? Mattt Thompson有一个很好的例子here

答案 2 :(得分:0)

我的解决方案是

- (NSString*)stringByTruncatingToWidth:(CGFloat)width maxHeight:(CGFloat)maxHeight font:(UIFont *)font;
    {
        NSString *ellipsis = @"…";
        NSMutableString *truncatedString = [self mutableCopy];
        if ([self textSizeForMaxWidth:width font:font].height > maxHeight)
        {
            truncatedString = [[truncatedString stringByAppendingString:ellipsis] mutableCopy];
            NSRange range = {truncatedString.length - 4, 1};
            [truncatedString deleteCharactersInRange:range];
            while ([truncatedString textSizeForMaxWidth:width font:font].height > maxHeight){
                [truncatedString deleteCharactersInRange:range];
                range.location--;
            }
        }
        return truncatedString;
    }

帮助计算最大宽度

的文字大小的方法
- (CGSize)textSizeForMaxWidth:(CGFloat)width font:(UIFont *)font
    {
        NSTextStorage *textStorage = [[NSTextStorage alloc]
                                      initWithString:self];
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: CGSizeMake(width, MAXFLOAT)];
        NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
        [layoutManager addTextContainer:textContainer];
        [textStorage addLayoutManager:layoutManager];
        [textStorage addAttribute:NSFontAttributeName value:font
                            range:NSMakeRange(0, [textStorage length])];
        [textContainer setLineFragmentPadding:0.0];

        [layoutManager glyphRangeForTextContainer:textContainer];
        CGRect frame = [layoutManager usedRectForTextContainer:textContainer];
        return frame.size;
    }