iOS開發筆記常用工具之富文本屬性介紹

前言

最近在項目中用到了圖文混排的功能,研究了一下之后發現還挺好玩的,因此寫一篇文章來記錄一下其中的一些知識。

Apple提供了二十來種樣式
UIKIT_EXTERN NSString * const NSFontAttributeName NS_AVAILABLE(10_0, 6_0);                // UIFont, default Helvetica(Neue) 12
UIKIT_EXTERN NSString * const NSParagraphStyleAttributeName NS_AVAILABLE(10_0, 6_0);      // NSParagraphStyle, default defaultParagraphStyle
UIKIT_EXTERN NSString * const NSForegroundColorAttributeName NS_AVAILABLE(10_0, 6_0);     // UIColor, default blackColor
UIKIT_EXTERN NSString * const NSBackgroundColorAttributeName NS_AVAILABLE(10_0, 6_0);     // UIColor, default nil: no background
UIKIT_EXTERN NSString * const NSLigatureAttributeName NS_AVAILABLE(10_0, 6_0);            // NSNumber containing integer, default 1: default ligatures, 0: no ligatures
UIKIT_EXTERN NSString * const NSKernAttributeName NS_AVAILABLE(10_0, 6_0);                // NSNumber containing floating point value, in points; amount to modify default kerning. 0 means kerning is disabled.
UIKIT_EXTERN NSString * const NSStrikethroughStyleAttributeName NS_AVAILABLE(10_0, 6_0);  // NSNumber containing integer, default 0: no strikethrough
UIKIT_EXTERN NSString * const NSUnderlineStyleAttributeName NS_AVAILABLE(10_0, 6_0);      // NSNumber containing integer, default 0: no underline
UIKIT_EXTERN NSString * const NSStrokeColorAttributeName NS_AVAILABLE(10_0, 6_0);         // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString * const NSStrokeWidthAttributeName NS_AVAILABLE(10_0, 6_0);         // NSNumber containing floating point value, in percent of font point size, default 0: no stroke; positive for stroke alone, negative for stroke and fill (a typical value for outlined text would be 3.0)
UIKIT_EXTERN NSString * const NSShadowAttributeName NS_AVAILABLE(10_0, 6_0);              // NSShadow, default nil: no shadow
UIKIT_EXTERN NSString *const NSTextEffectAttributeName NS_AVAILABLE(10_10, 7_0);          // NSString, default nil: no text effect

UIKIT_EXTERN NSString * const NSAttachmentAttributeName NS_AVAILABLE(10_0, 7_0);          // NSTextAttachment, default nil
UIKIT_EXTERN NSString * const NSLinkAttributeName NS_AVAILABLE(10_0, 7_0);                // NSURL (preferred) or NSString
UIKIT_EXTERN NSString * const NSBaselineOffsetAttributeName NS_AVAILABLE(10_0, 7_0);      // NSNumber containing floating point value, in points; offset from baseline, default 0
UIKIT_EXTERN NSString * const NSUnderlineColorAttributeName NS_AVAILABLE(10_0, 7_0);      // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString * const NSStrikethroughColorAttributeName NS_AVAILABLE(10_0, 7_0);  // UIColor, default nil: same as foreground color
UIKIT_EXTERN NSString * const NSObliquenessAttributeName NS_AVAILABLE(10_0, 7_0);         // NSNumber containing floating point value; skew to be applied to glyphs, default 0: no skew
UIKIT_EXTERN NSString * const NSExpansionAttributeName NS_AVAILABLE(10_0, 7_0);           // NSNumber containing floating point value; log of expansion factor to be applied to glyphs, default 0: no expansion

UIKIT_EXTERN NSString * const NSWritingDirectionAttributeName NS_AVAILABLE(10_6, 7_0);    // NSArray of NSNumbers representing the nested levels of writing direction overrides as defined by Unicode LRE, RLE, LRO, and RLO characters.  The control characters can be obtained by masking NSWritingDirection and NSWritingDirectionFormatType values.  LRE: NSWritingDirectionLeftToRight|NSWritingDirectionEmbedding, RLE: NSWritingDirectionRightToLeft|NSWritingDirectionEmbedding, LRO: NSWritingDirectionLeftToRight|NSWritingDirectionOverride, RLO: NSWritingDirectionRightToLeft|NSWritingDirectionOverride,

UIKIT_EXTERN NSString * const NSVerticalGlyphFormAttributeName NS_AVAILABLE(10_7, 6_0);   // An NSNumber containing an integer value.  0 means horizontal text.  1 indicates vertical text.  If not specified, it could follow higher-level vertical orientation settings.  Currently on iOS, it's always horizontal.  The behavior for any other value is undefined.

可以看到最低支持版本包括了iOS6和iOS7,所以不用擔心版本兼容問題。

好了部分介紹下(實際開發中視情況使用)
首先定義了一些測試用的字符串和一個UILabel
static NSString *const kTestString1 = @"測試字符串1";
static NSString *const kTestString2 = @"測試字符串段落1\n測試字符串段落2";
static NSString *const kTestString3 = @"I am ForKid";

-(UILabel *)testLabel{
    if (!_testLabel) {
        _testLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, kWidth - 20, kHeight)];
        _testLabel.backgroundColor = [UIColor lightGrayColor];
        _testLabel.numberOfLines = 0;
        _testLabel.font = [UIFont boldSystemFontOfSize:50.f];
    }
    return _testLabel;
}
1.文字字體NSFontAttributeName:這個用來設置文字的字體Font,這個大家都會使用的。
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:40.f] range:range];
    self.testLabel.attributedText = attributeString;
運行效果:
字體.png
2.文字前景色NSForegroundColorAttributeName:這個其實就是文字的顏色
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];
    self.testLabel.attributedText = attributeString;
運行效果
文字前景色.png
3.文字背景色
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor] range:range];
    self.testLabel.attributedText = attributeString;
運行效果
文字背景色.png
4.連字符NSLigatureAttributeName:這個一般情況下不會用到,沒有做過多的測試,而且有些字體還不支持。
實例
    NSRange range = NSMakeRange(0, kTestString3.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString3];
    //0無連體效果,1連體效果
    [attributeString addAttribute:NSLigatureAttributeName value:@(1) range:range];
    self.testLabel.attributedText = attributeString;
這個就沒有運行圖了
test.jpg
5.字符間距NSKernAttributeName:這個就是在渲染文字的時候文字于文字之間的間距,value是NSNumber類型。
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSKernAttributeName value:@(20) range:range];
    self.testLabel.attributedText = attributeString;
運行效果:
字符間距.png
6.刪除線NSStrikethroughStyleAttributeName:這個屬性有點特殊,它分為兩個樣式:單刪除線、雙刪除線。具體的顯示根據設置的值來確定
實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    //1~7單線,依次加粗
    //9~15:雙線,依次加粗
    [attributeString addAttribute:NSStrikethroughStyleAttributeName value:@(7) range:range];
    self.testLabel.attributedText = attributeString;
運行效果:
  • 單線


    刪除線_單線.png
  • 雙線


    刪除線_雙線.png
另外,還可以設置刪除線的顏色NSStrikethroughColorAttributeName
實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSStrikethroughStyleAttributeName value:@(7) range:range];
    [attributeString addAttribute:NSStrikethroughColorAttributeName value:[UIColor blueColor] range:range];
    self.testLabel.attributedText = attributeString;
運行效果
刪除線顏色.png
7.下劃線NSUnderlineStyleAttributeName:文字下劃線,可以指定樣式以及顏色。
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    //1~7單線,依次加粗
    //9~15:雙線,依次加粗
    [attributeString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleThick) range:range];
    [attributeString addAttribute:NSUnderlineColorAttributeName value:[UIColor redColor] range:range];
    self.testLabel.attributedText = attributeString;
運行效果:
下劃線.png
tips:關于下劃線具體的樣式后續補充
8.鏤空和描邊NSStrokeColorAttributeNameNSStrokeWidthAttributeName:用于文字顯示效果的文字邊框線條粗細和顏色。
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    //正值鏤空,負值描邊
    [attributeString addAttribute:NSStrokeColorAttributeName value:[UIColor redColor] range:range];
    [attributeString addAttribute:NSStrokeWidthAttributeName value:@(2) range:range];
    self.testLabel.attributedText = attributeString;
運行效果
  • 鏤空


    描邊.png
  • 描邊


    填充.png
9.陰影效果NSShadowAttributeName:給文字添加陰影效果。
實例:
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];

    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowOffset = CGSizeMake(5, 5);
    shadow.shadowColor = [UIColor redColor];
    shadow.shadowBlurRadius = 0;
    
    [attributeString addAttribute:NSShadowAttributeName value:shadow range:range];
    self.testLabel.attributedText = attributeString;
運行效果:
陰影效果.png
10.超鏈接NSLinkAttributeName:給文字添加一個超鏈接,并且顯示效果會變成藍色而且在文字下方添加下劃線,想要點擊的話如果是UITextView,需要在中實現相應的代理方法
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction NS_AVAILABLE_IOS(10_0);

或者

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");

具體的實現內容我會在后面的文章中介紹

實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSLinkAttributeName value:@"https://www.baidu.com" range:range];
    self.testLabel.attributedText = attributeString;
運行效果
超鏈接.png
11.基線偏移量NSBaselineOffsetAttributeName:這個是設置文字渲染時的偏移量。我還沒怎么用到過,不過有一個情況可以使用,比如用于文檔注釋時的腳注
實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSUnderlineStyleAttributeName value:@(2) range:range];
    [attributeString addAttribute:NSUnderlineColorAttributeName value:[UIColor redColor] range:range];
    [attributeString addAttribute:NSBaselineOffsetAttributeName value:@(0) range:range];
    
    
    NSMutableAttributedString *attributeString2 = [[NSMutableAttributedString alloc] initWithString:@"偏移測試"];
    [attributeString2 addAttribute:NSUnderlineStyleAttributeName value:@(2) range:NSMakeRange(0, 4)];
    [attributeString2 addAttribute:NSUnderlineColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 4)];
    [attributeString2 addAttribute:NSBaselineOffsetAttributeName value:@(-20) range:NSMakeRange(0, 4)];
    
    [attributeString appendAttributedString:attributeString2];
    self.testLabel.font = [UIFont boldSystemFontOfSize:16.f];
    self.testLabel.attributedText = attributeString;
運行效果
基線偏移量.png
12.傾斜NSObliquenessAttributeName:這個一般很少用到。
實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    //正值右傾,負值左傾
    [attributeString addAttribute:NSObliquenessAttributeName value:@(1) range:range];
    self.testLabel.attributedText = attributeString;
運行效果
文字傾斜.png
13.拉伸NSExpansionAttributeName:拉伸字符,這個和字符間距是不一樣的。
實例
    NSRange range = NSMakeRange(0, kTestString1.length);
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    [attributeString addAttribute:NSExpansionAttributeName value:@(1) range:range];
    self.testLabel.attributedText = attributeString;   
運行效果
字符拉伸.png
14.圖文混排NSAttachmentAttributeName
實例
    NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:kTestString1];
    UIImage *image = [UIImage imageNamed:@"test.jpg"];
    
    //創建一個NSTextAttachement對象
    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    attachment.image = image;
    CGFloat height = [kTestString1 sizeWithAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:24.f]}].height;
    //如果寬度大于剩余的寬度 則會從另行開始
    attachment.bounds = CGRectMake(0, 0, height, height);

    NSAttributedString *att = [NSAttributedString attributedStringWithAttachment:attachment];
    //拼接到最后面
    [attributeString appendAttributedString:att];
    //放入指定位置
    [attributeString insertAttributedString:att atIndex:3];
    
    self.testLabel.font = [UIFont boldSystemFontOfSize:24.f];
    self.testLabel.attributedText = attributeString;
運行效果
圖文混排.png
Tips:
1.關于圖文混排這里只是一個小小的演示效果,一般情況下需求比這個多很多,我都會在后續的文章當中做出對應的演示和說明以及Demo。
2.后續我會對當前比較流行的混排框架:比如YYText、DTCoreText以及TYAttributedLabel等三方庫的使用做出介紹。
3.另外現在很多時候會通過解析HTML數據來獲取數據,或者直接解析一段HTML源碼來渲染出對應的文本信息,我也會在后續文章中介紹到,包括用到的三方框架和工具以及部分原理。
4.最近項目中用到了文本富文本編輯器,完成之后,我會分享一下。
15.段落樣式NSParagraphStyleAttributeName:關于段落樣式,這里不做解釋,我在另一篇文章當中有做介紹和基本使用方法。

以上就是開發中常用的對字符串處理的方式,本文對應的Demo可以點擊這里下載.

如果您有任何問題或者好的建議歡迎留言評論指正。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容