Truncate UILabel in specific location

后端 未结 3 1323
小蘑菇
小蘑菇 2021-01-20 03:18

I use a table view to show a list of books, where each cell has a UILabel that shows the book\'s name and another UILabel the shows the book\'s aut

3条回答
  •  天涯浪人
    2021-01-20 03:40

    This answer is based on https://stackoverflow.com/a/30813691/2123122. Here is the sample code.

    @interface CustomLabel()
    
      @property (nonatomic, retain) NSLayoutManager *layoutManager;
      @property (nonatomic, retain) NSTextContainer *textContainer;
      @property (nonatomic, retain) NSTextStorage *textStorage;
    
    @end
    
    @implementation CustomLabel
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
           self = [super initWithCoder:aDecoder];
           if (self) {
             [self configureTextkitStack];
           }
           return self;
     }
     - (instancetype)initWithFrame:(CGRect)frame {
           self = [super initWithFrame:frame];
           if (self) {
             [self configureTextkitStack];
           }
           return self;
      }
    
    - (void)configureTextkitStack {
          _textContainer = [[NSTextContainer alloc] init];
          _textContainer.lineFragmentPadding = 0;
          _textContainer.maximumNumberOfLines = self.numberOfLines;
          _textContainer.lineBreakMode = self.lineBreakMode;
          _textContainer.widthTracksTextView = YES;
    
          _layoutManager = [[NSLayoutManager alloc] init];
          [_layoutManager addTextContainer:self.textContainer];
    
          [_textContainer setLayoutManager:self.layoutManager];
    
          _textStorage = [[NSTextStorage alloc] init];
          [_textStorage addLayoutManager:self.layoutManager];
          [self.layoutManager setTextStorage:_textStorage];
    }
    
    - (NSRange)rangeForTokenInsertion {
          self.textContainer.size = self.bounds.size;
          if (self.attributedText.length > 0 ){
            [self.textStorage setAttributedString:[[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText]];
          }
          if (self.text.length == 0) {
            return NSMakeRange(NSNotFound, 0);
          }
    
          NSInteger glyphIndex = [self.layoutManager glyphIndexForCharacterAtIndex:self.textStorage.length - 1];
          NSRange range = [self.layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:glyphIndex];
    
          return range;
        }
    

    Now you can use this as follows:

     NSRange range = [self.label rangeForTokenInsertion];
     NSString *token = @"...+2 authors";
     if (range.location != NSNotFound ) {
      range.length += token.length;
      range.location -= token.length;
     }
     if (range.location != NSNotFound) {
      NSString *finalString = [self.label.text  stringByReplacingCharactersInRange:range withString:token];
      self.label.text = finalString;
     }
    

    I have created a UILabel subclass called ResponsiveLabel which handles custom truncation token as well as applying styles to patterns like userhandles, URLs, hashtags etc.

提交回复
热议问题