iOS 文字超出行数限制末尾添加高亮可点击字

  先上效果图


custom1.png
custom2.png

在做文字超出行数限制末尾添加高亮点击字的需求的时候,遇到的这么一个问题。

如果只是在末尾追加高亮点击字,直接用yytext 就可以了。
原本我也是直接用yytext处理掉。 yytext 效果如下:


yytext.png

好像完全满足,然而有一种情况,我们产品不想要这样。这段文字中间加了个换行,导致高亮字的那一行末尾是空的 的情况,yytext效果如下:


yytext2.png

而我们的产品要的是这种情况也显示在最后。我用yytext没试出来。所以没的办法,只有自己想法子,最后就采用了下面我用的方式。
分为3个点
  • 获取Label上每一行的文字
  • 超出限制行数,将最大行文字做处理(如果增加了高亮字,但是高亮字+文字的width不够一行的width,进行补空格操作)
  • 获取点击是否在高亮字上
    首先通过CoreText里的CTFramesetter,CTFrame来获取每一行的文字,如下:
//获取每行文字
- (NSArray *)getSeparatedLinesWithWidth:(CGFloat)width
{
    NSString *text = [self text];
    if (!text || text.length<1) {
        return 0;
    }
    UIFont *font = [self font];
    CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,width,100000));
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
    for (id line in lines) {
        CTLineRef lineRef = (__bridge CTLineRef )line;
        CFRange lineRange = CTLineGetStringRange(lineRef);
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
        NSString *lineString = [text substringWithRange:range];
        [linesArray addObject:lineString];
        
    }
    return linesArray;
    
}

然后根据获取到的每一行文字,做行数限制及补空格,高亮字的处理。
最后通过NSLayoutManager, NSTextContainer and NSTextStorage来判断点击处是否在高亮字上,详细代码可看demo

- (BOOL)didTapAttributedTextInLabel:(UILabel *)label inRange:(NSRange)targetRange {
    NSParameterAssert(label != nil);
    
    CGSize labelSize = label.bounds.size;
    // create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:labelSize];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:label.attributedText];

    // configure layoutManager and textStorage
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    // configure textContainer for the label
    textContainer.lineFragmentPadding = 0.0;
    textContainer.lineBreakMode = label.lineBreakMode;
    textContainer.maximumNumberOfLines = label.numberOfLines;

    // find the tapped character location and compare it to the specified range
    CGPoint locationOfTouchInLabel = [self locationInView:label];
    CGRect textBoundingBox = [layoutManager usedRectForTextContainer:textContainer];
    CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
                                              (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
    CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
                                                         locationOfTouchInLabel.y - textContainerOffset.y);
    NSInteger indexOfCharacter = [layoutManager characterIndexForPoint:locationOfTouchInTextContainer
                                                       inTextContainer:textContainer
                              fractionOfDistanceBetweenInsertionPoints:nil];

    if (NSLocationInRange(indexOfCharacter, targetRange)) {
        return YES;
    } else {
        return NO;
    }
    
}

也可以根据自己的业务需求,在代码里做一些改动,代码不多,简单易懂,不改动的可以直接拿我的分类用。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.badgeVaule气泡提示 2.git终端命令方法> pwd查看全部 >cd>ls >之后桌面找到文件夹内容...
    i得深刻方得S阅读 4,792评论 1 9
  • 今天走在街上闻到几缕似有似无的兰花香味。谁也是兰花爱好者?
    云锦花源阅读 190评论 0 0
  • 前言 最近,新项目中,有些相应的需求,要在特殊形状的view中展示数据,然后里边还有些直线,虚线的结合,考虑到使用...
    wwwwwwdi阅读 1,028评论 0 4
  • 前段时间同学小聚,有人慨然长叹,转眼间毕业都五年了!顿时,在座几人相顾哑然,摇头,彼此眼中看到的是平凡80后面对当...
    红尘扁舟阅读 438评论 9 5
  • 准备睡觉,发现没有日更。好紧张。还有几分钟。我不想再次失败! 今天辟谷第六天。感觉越来越好。居然没有吃枣子。就吃了...
    家鸣妈妈1阅读 205评论 0 1