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

新版的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:kCTLineBreakByCharWrapping lineSpacing: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的设置小了,所以少分了一行

自行更正,我不改例子了


FXLabel支持中文行距的简单修改_第1张图片


你可能感兴趣的:(FXLabel支持中文行距的简单修改)