iOS中自動斷字(hyphenationFactor)的使用

weixin_33785972發表於2017-12-26

專案中某個cell需要顯示一個長文字,要求是中英文都要顯示。英文如果在行尾需要用-拆分為兩個。我們知道如果要把英文拆分,應該用NSLineBreakByCharWrapping,

於是我們寫了如下程式碼:

    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:content];

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    //兩邊對齊
    paragraphStyle.alignment = NSTextAlignmentJustified;
    paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
    CGFloat offset = 2;
    [paragraphStyle setLineSpacing:offset];

    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, content.length)];

    self.carName.attributedText = attributedString;

但是如果文字過長,就會發現有的顯示不出來,如圖:


4822184-6a8a987817ce9449.png
9CC52B74-D52C-4F3A-B652-89888C479947.png

(照顧隱私,加了馬賽克)
於是我們想起來,應該用NSLineBreakByTruncatingTail在文字末尾顯示省略號,然而,然而,NSLineBreakByTruncatingTail 和NSLineBreakByCharWrapping,這兩個是同一個屬性的, 我們檢視下NSParagraphStyle的lineBreakMode這個屬性,發現並不是位操作符。這可咋整啊。。
經過反覆查詢,功夫不負有心人。找到了一篇文章。

UILabel中英文顯示折行
發現了paragraphStyle的hyphenationFactor這個屬性。
在 Apple 開發者參考文件中,我們能找到 TextKit 有關自動斷字

hyphenationFactor屬性的描述:
檢視下文件中

Hyphenation is attempted when the ratio of the text width (as broken without hyphenation) to the width of the line fragment is less than the hyphenation factor. When the paragraph’s hyphenation factor is 0.0, the layout manager’s hyphenation factor is used instead. When both are 0.0, hyphenation is disabled. This property detects the user-selected language by examining the first item in preferredLanguages.

Soga,這個是連字元屬性,取值 0 到 1 之間,可以斷詞。(具體設定為0.幾,文章中說了,我也沒太看明白。於是我就設定了0.7)
在上面的程式碼中加上這句話:

paragraphStyle.hyphenationFactor = 0.7;

重新跑一遍。。。。。。
為啥不好使!
繼續按關鍵詞hyphenationFactor找吧。找到了這篇文章

使用 hyphenationFactor 渲染別國語言

按照文章中,給NSLocale加了個Category,將preferredLanguages轉換為英文。

#import "NSLocale+ForceHyphenation.h"

@implementation NSLocale (ForceHyphenation)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        SEL originalSelector = @selector(preferredLanguages);
        SEL swizzledSelector = @selector(sr_preferredLanguages);

        Class class = object_getClass((id)self);
        Method originalMethod = class_getClassMethod(class, originalSelector);
        Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}
+ (NSArray <NSString *> *)sr_preferredLanguages {
    [self sr_preferredLanguages];
    return @[ @"en" ];
}

@end

build..
run..
...


4822184-49f2c48e5c58008f.png
3CF3DF8C-82AA-4B12-AFE2-C47D277F1CFC.png

好激動,終於成功了。。
???????

寫這篇文章,希望有相同遭遇的同學能看到吧。

另外,利用YYText設定truncationToken可以完美的實現這項功能,而且效率比這個高,感興趣的同學可以看下下面的demo:

https://github.com/zgsddzwj/WJLabelDemo

本人QQ:297959735 郵箱:zgsddzwj@163.com,歡迎提意見。

參考文章:
自動斷字 ( Auto Hyphenation ) 是什麼,為什麼你的 App 裡應該使用它

相關文章