FXLabel支持中文行距的简单修改

来源:互联网 发布:空间数据质量国家标准 编辑:程序博客网 时间:2024/05/19 06:36

新版的FXLabel已经可以支持设置行间距了,但发现不能支持中文,遂简单改写了一下应急用

主要修改函数:

- (NSArray *)FXLabel_linesWithFont:(UIFont *)font
                 constrainedToSize:(CGSize)size
                     lineBreakMode:(NSLineBreakMode)lineBreakMode
                       lineSpacing:(CGFloat)lineSpacing
                  characterSpacing:(CGFloat)characterSpacing
                      kerningTable:(NSDictionary *)kerningTable
                      allowOrphans:(BOOL)allowOrphans

此函数中函数word的识别是根据“ ”空格区分的,中文字之间没有,所以识别上有问题。

简单的修改思路是将每个字符作为一个word,也就是类似NSLineBreakByCharWrapping模式


修改代码如下:

- (NSArray *)FXLabel_linesWithFont:(UIFont *)font                 constrainedToSize:(CGSize)size                     lineBreakMode:(NSLineBreakMode)lineBreakMode                       lineSpacing:(CGFloat)lineSpacing                  characterSpacing:(CGFloat)characterSpacing                      kerningTable:(NSDictionary *)kerningTable                      allowOrphans:(BOOL)allowOrphans{    //TODO: handle lineBreakMode of type NSLineBreakByCharWrapping    //this will require splitting text into individual characters        //split text into words    NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];    for (int i=0; i<self.length; i++)    {        NSString *str = [self substringWithRange:NSMakeRange(i,1)];        NSLog(@"%@", str);        [array addObject:str];    }    NSArray *words = [NSArray arrayWithArray:array];//    NSString *text = [self stringByReplacingOccurrencesOfString:@"\t" withString:@" "];//    text = [text stringByReplacingOccurrencesOfString:@"\n" withString:@" \n "];    // 空格作为分隔符//    NSArray *words = [text componentsSeparatedByString:@" "];    words = [words filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]];        //calculate lines    NSInteger index = 0;    NSMutableArray *lines = [NSMutableArray array];    while (index < [words count])    {        NSInteger lineCount = [lines count];        if (lineCount && ((lineCount + 1) * font.lineHeight + lineCount * font.pointSize * lineSpacing) > size.height)        {            //append remaining text to last line            NSArray *remainingWords = [words subarrayWithRange:NSMakeRange(index, [words count] - index)];            NSString *line = [lines lastObject];            // 加回空格分隔符            //NSString *newLine = [line length]? [line stringByAppendingString:@" "]: @"";            NSString *newLine = [line length]? line : @"";            // 加回空格分隔符            //newLine = [newLine stringByAppendingString:[remainingWords componentsJoinedByString:@" "]];            newLine = [newLine stringByAppendingString:[remainingWords componentsJoinedByString:@""]];            newLine = [newLine stringByReplacingOccurrencesOfString:@"\n " withString:@"\n"];            newLine = [newLine stringByReplacingOccurrencesOfString:@" \n" withString:@"\n"];            [lines replaceObjectAtIndex:lineCount - 1 withObject:newLine];            break;        }        NSString *line = nil;        for (int i = index; i < [words count]; i++)        {            NSString *word = words[i];            // 加回空格分隔符            //NSString *newLine = line? [line stringByAppendingFormat:@" %@", word]: word;            NSString *newLine = line? [line stringByAppendingFormat:@"%@", word]: word;            CGFloat lineWidth = [newLine sizeWithFont:font                                          minFontSize:font.pointSize                                       actualFontSize:NULL                                             forWidth:INFINITY                                        lineBreakMode:lineBreakMode                                     characterSpacing:characterSpacing                                         kerningTable:kerningTable].width;                        if ([word isEqualToString:@"\n"])            {                //add line and prepare for next                [lines addObject:line ?: @""];                index = i + 1;                break;            }            else if ([word isEqualToString:@"\r"])            {                //add line and prepare for next                [lines addObject:line ?: @""];                index = i + 1;                break;            }            else if (lineWidth > size.width && line)            {                //check for orphans                if (!allowOrphans && i > 0 &&                    (i == [words count] - 1 || [words[i + 1] isEqualToString:@"\n"] || [words[i + 1] isEqualToString:@"\r"]) &&                    ![words[i - 1] FXLabel_isPunctuation])                {                    //force line break                    NSRange range = [line rangeOfString:@" " options:NSBackwardsSearch];                    if (range.location != NSNotFound)                    {                        line = [line substringToIndex:range.location];                        i --;                    }                }                                //add line and prepare for next                [lines addObject:line];                index = i;                break;            }            else if (i == [words count] - 1)            {                //add line and finish                [lines addObject:newLine];                index = i + 1;                break;            }            else            {                //continue                line = newLine;            }        }    }    return lines;}


例子下载:Linespacing & Orphans


更正一下:

    CGSize size = [str sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(320, 999999.0f) lineBreakMode:kCTLineBreakByCharWrappinglineSpacing:0.8 characterSpacing:0 kerningTable:nil allowOrphans:NO];
    CGRect frame = CGRectMake(0, 0, 320, size.height);
    l1.frame = frame;
    l1.text = str;
    l1.backgroundColor = [UIColor clearColor];
    l1.textColor = [UIColor redColor];
    l1.lineSpacing = 1;
例子中的这段代码,计算size时的lineSpacing写成了0.8比label的设置小了,所以少分了一行

自行更正,我不改例子了