Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/114.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何设置UITextView的最大高度和固定宽度,并在溢出时强制省略号而不是滚动?_Ios_Iphone_Ios7_Uitextview_Nsattributedstring - Fatal编程技术网

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

Ios 如何设置UITextView的最大高度和固定宽度,并在溢出时强制省略号而不是滚动?,ios,iphone,ios7,uitextview,nsattributedstring,Ios,Iphone,Ios7,Uitextview,Nsattributedstring,我的目标是: 我希望使用UITextView而不是UILabel,因为我希望用户能够选择文本并进行复制 我希望UITextView在60点的高度最大 我希望UITextView具有300点的固定宽度 我希望UITextView在单词上换行 假设,根据我输入的属性文本字符串,需要3行才能达到最大高度60点。因此,如果我向UITextView输入6行属性文本,我希望UITextView在60点处最大输出,并显示3行,后跟省略号(例如…) 我不希望文本视图永远是可滚动的 如果我将单个单词作为属性文本(

我的目标是:

  • 我希望使用UITextView而不是UILabel,因为我希望用户能够选择文本并进行复制
  • 我希望UITextView在60点的高度最大
  • 我希望UITextView具有300点的固定宽度
  • 我希望UITextView在单词上换行
  • 假设,根据我输入的属性文本字符串,需要3行才能达到最大高度60点。因此,如果我向UITextView输入6行属性文本,我希望UITextView在60点处最大输出,并显示3行,后跟省略号(例如…)
  • 我不希望文本视图永远是可滚动的
  • 如果我将单个单词作为属性文本(如“Hello”)提供给UITextView,我希望UITextView仍具有300点的固定宽度,但动态高度尽可能小,在本例中,一行文本大约有20点
  • 我希望UITextView具有零内部填充
  • 有什么想法吗

    - (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和width:(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;
    }
    

    您是否考虑过将UILabel子类化并添加选择和复制文本的功能?马特·汤普森有一个很好的例子。

    我的解决方案是

    - (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;
        }
    

    几乎所有这些问题都是通过
    UITextView
    官方文档直接解决的,其余的则是间接解决的。。。我已经广泛阅读了文档,并花了8个多小时来编写代码。是的,这看起来很简单,但很难实现。我一直无法做到这一点,所以我现在终于请求帮助。如果你已经花了8个小时在这上面,一个好的开始将包括你迄今为止所做的努力,你能够完成的这一长串目标中的什么,以及你在这张清单上留下了什么。这张清单上的很多东西都非常基本和简单,虽然重要的是要包括你所需要的所有要求,如帖子所示,但不包括你迄今为止的努力和你的具体问题,看起来你只是要求某人花一两个小时为你设计一个自定义控件。@nhgrif我发布了我自己的答案。这是你期待的非常基本和直截了当的答案吗?我不喜欢它b/c它要求字符串越来越短,每个周期缩短3个字符(while loop)。关于如何提高效率,有什么想法吗?关于如何使代码更加优雅的技巧,我建议在CodeReview上以问题的形式发布您的答案:无论如何,我并不是说整个解决方案都是直接的和基本的,只是说很多方面都是简单的(单词换行、没有滚动、填充等,许多已经存在的UITextView属性),并且您的答案根本没有显示出任何努力(特别是在这个问题的简单方面),这让问题看起来像是您只是想让某人为您编写代码,而不是。。。