美文网首页
iOS 获取固定宽度下的可见字符串

iOS 获取固定宽度下的可见字符串

作者: talon23333 | 来源:发表于2022-08-01 17:35 被阅读0次

    我们知道当UILabel显示不下内容时,会自动截断处理,我们还可以用lineBreakMode来修改截断方式。当我们限定只能截断某些字符时,系统提供的截断方式就不能满足了。

    自定义截断字符时,就会遇到一个问题,固定宽度下能显示多少字符串?

    使用场景

    偶尔收到了微信的专属红包,发现当微信名或备注较长时,会将用户名截断显示。

    微信专属红包,昵称较长时显示如下:

    给ABCDEFGHI...的专属红包
    ABCDEFGHI...已领取

    实现逻辑分析

    微信红包气泡宽度是相对固定的,所以红包状态的宽度也是固定的。当用户名过长时,要保证其他字符能完整显示,只能截断用户名。

    //其他字符
    给xxx的专属红包
    
    总宽度 = 其他字符宽度 + 用户名宽度(可截断)
    

    由上我们知道,算出其他字符的宽度后,就能得到用户名宽度。拿到用户名可显示的宽度后,怎么知道能显示多少内容呢?

    实现流程

    查资料发现可以用CTFrame获取可见字符串范围 CTFrameGetVisibleStringRange

    CFRange CTFrameGetVisibleStringRange(CTFrameRef frame);
    

    由上定义,我们还需要创建一个CTFrameRef,需用到 CTFramesetterCreateFrame

    CTFrameRef CTFramesetterCreateFrame(CTFramesetterRef framesetter, CFRange stringRange, CGPathRef path, CFDictionaryRef frameAttributes);
    

    通过path参数,我们可以传入宽度限制,即可得到固定宽度下的可见字符串范围。

    上代码

    最好写在NSStringCategory中,需要导入CoreText框架。

    注意:其中path的高度需大于font.lineHeight,小于2倍font.lineHeight,当大于2倍font.lineHeight时,将按照多行来计算可显示的内容。

    #import "NSString+STExtension.h"
    #import <CoreText/CoreText.h>
    
    
    /// 获取固定宽度下的可见字符串
    /// @param width 宽度
    /// @param font 字体
    /// @param showEllipsis 结尾是否展示省略号
    - (NSString *)getVisibleStringWithWidth:(CGFloat)width font:(UIFont*)font showEllipsis:(bool)showEllipsis
    {
        if (width == 0) {
            return @"";
        }
        NSMutableParagraphStyle *p = [[NSMutableParagraphStyle alloc] init];
        p.lineBreakMode = NSLineBreakByCharWrapping;
        
        NSAttributedString *namesAtt = [[NSAttributedString alloc] initWithString:self attributes:@{NSFontAttributeName:font, NSParagraphStyleAttributeName:p}];
        CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)namesAtt);
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, width, font.lineHeight + 1.0)];
        CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, self.length), path.CGPath, NULL);
        
        CFRange range = CTFrameGetVisibleStringRange(frame);
        CFRelease(framesetter);
        CFRelease(frame);
        NSString *resultStr = [self substringWithRange:NSMakeRange(range.location, range.length)];
        if (showEllipsis && resultStr.length < self.length && resultStr.length > 0) {
            resultStr = [resultStr stringByReplacingCharactersInRange:NSMakeRange(resultStr.length - 1, 1) withString:@"..."];
        }
        return resultStr;
    }
    

    最后

    感谢阅读,有问题欢迎讨论。

    参考文章:NSString根据宽度获得能显示出的字符串

    相关文章

      网友评论

          本文标题:iOS 获取固定宽度下的可见字符串

          本文链接:https://www.haomeiwen.com/subject/ghvrwrtx.html