若是遇到上面一個需求, 你會怎麼處理, 若干個 UILabel + UIImageView? NSAttributedString拼接? CoreText?git
我相信不管是哪一種方式代碼量都不小, 而且難以複用, 其餘語言寫富文本是那麼輕鬆, Android 天生支持簡單 HTML, RN(JS) 標籤套標籤, 而只要用過 iOS 中的富文本都會以爲難用... 目前業界功能強大、較爲好用的是 YYText, 但設計思想是儘量與 UILabel、UITextView 類似, 因此相對使用也不是特別簡單, 並且框架較重. 基於現狀開發了一套輕量的框架, 知足大部分富文本需求, 而且提供了手勢響應、 繪製回調、 圖文對齊、 CoreText 屬性擴展、 支持網絡圖片、 異步繪製性能優化, 最重要的是使用簡單, 經過鏈式語法輕鬆寫出一篇圖文混排文本.github
如圖所示一片圖文混排, 涉及到字體, 顏色, 字間距, 行間距, 圖片對齊, 文字對齊, 描邊等等屬性, 還有網絡圖片與本地圖片混排, 手勢響應等需求, 使用本框架能夠下面這樣實現:web
//...省略常量聲明
TextBuild
.append(title).font(titleFont).color(titleColor).onClicked(titleOnClicked).onLayout(titleOnLayout)
.append(firstPara).color(firstParaColor).align(@0)
.append(webImage).font(separateLineFont).minLineHeight(@100)
.append(separateLine).font(separateLineFont).strokeColor(separateLineColor).strokeWidth(@1).horizontalOffset(@30)
.append(locolImage).horizontalOffset(@30)
.append(lastPara).font(lastParaFont).align(@1).maxLineHeight(@20)
.append(bookName).font(bookNameFont).color(bookNameColor).onClicked(bookOnClicked).align(@1)
.append(lineLayer).attachSize(lineLayerSize)
.append(quote).color(quoteColor).letterSpace(@0).minLineSpace(@8).align(@0)
.append(buyButton).attachSize(buyButtonSize).attachAlign(@0)
//設置全局默認屬性, 優先級低於指定屬性
.entire().maxSize(maxSize).align(@2).letterSpace(@3).minLineHeight(@20).attachAlign(@1).onClicked(textOnClicked).attachSize(attachSize).shadow(shadow).cornerRadius(@50).backgroundLayer(gradientLayer).horizontalMargin(@10).preferHeight(@(preferHeight))
//繪製View
.drawView(^(UIView *drawView) {
[self.view addSubview:drawView];
});
複製代碼
而在實際需求中也能夠根據不一樣條件對 NSString 進行組合, 最後繪製:緩存
//...省略常量聲明
//拼接文章
//標題
NSString *titleString = TextBuild.append(title).font(titleFont).color(titleColor).onClicked(titleOnClicked).onLayout(titleOnLayout);
//首段
NSString *firstParaString = TextBuild.append(firstPara).color(firstParaColor).align(@0);
//圖片須要用一個空字符串起頭
NSString *webImageString = TextBuild.append(webImage).font(separateLineFont).minLineHeight(@100);
//分割線
NSString *separateLineString = TextBuild.append(separateLine).font(separateLineFont).strokeColor(separateLineColor).strokeWidth(@1).horizontalOffset(@30);
//本地圖片
NSString *locolImageString = TextBuild.append(locolImage).horizontalOffset(@30);
//最後一段
NSString *lastParaString = TextBuild.append(lastPara).font(lastParaFont).align(@1).maxLineHeight(@20);
//書名
NSString *bookNameString = TextBuild.append(bookName).font(bookNameFont).color(bookNameColor).onClicked(bookOnClicked).align(@1).maxLineHeight(@20);
//引用線Layer
NSString *lineLayerString = TextBuild.append(lineLayer).attachSize(lineLayerSize);
//引用
NSString *quoteString = TextBuild.append(quote).color(quoteColor).letterSpace(@0).minLineSpace(@8).align(@0);
//按鈕
NSString *buttonString = TextBuild.append(buyButton).attachSize(buyButtonSize).attachAlign(@0);
//設置全局默認屬性, 優先級低於指定屬性
NSString *defaultAttributes = TextBuild.entire()
.maxSize(maxSize).align(@2).letterSpace(@3).minLineHeight(@20).attachAlign(@1).onClicked(textOnClicked).attachSize(attachSize).shadow(shadow).cornerRadius(@50).backgroundLayer(gradientLayer).horizontalMargin(@10).preferHeight(@(preferHeight));
//拼接
TextBuild
.append(titleString)
.append(firstParaString)
.append(webImageString)
.append(separateLineString)
.append(locolImageString)
.append(lastParaString)
.append(bookNameString)
.append(lineLayerString)
.append(quoteString)
.append(buttonString)
//設置默認屬性
.append(defaultAttributes)
//繪製Layer
.drawLayer(^(CALayer *drawLayer) {
[self.view.layer addSublayer:drawLayer];
});
複製代碼
對 NSString 的擴展, 操做字符串生成繪製對應視圖ruby
append(id content)性能優化
拼接
content 能夠是文本(NSString)、圖片(UIImage)、圖片連接(NSURL)(必須指定attachSize屬性)、視圖(CALayer/UIView)
複製代碼
entire()網絡
設置整段富文本
優先級低於指定屬性, 較爲重要的屬性 maxSize 設置繪製約束, 部分段落屬性只在整段中設置生效
複製代碼
drawLayer(^(CALayer *drawLayer)completion)app
繪製layer, 沒法響應手勢, 當有UIView混排建議使用 drawView
複製代碼
drawView(^(UIView *drawView)completion)框架
繪製View, 可響應手勢, 建議使用此API
複製代碼
整體採用 CoreText + 異步繪製圖片完成, 理論上性能會比較高, 通過測試以下數據供參考:異步
內容: 一段文本加上兩張圖片
機型: iPhone 6
測試結果:
常規(使用NSAttributedString + UILabel)過程: 建立->顯示(繪製) 常規分析:
異步繪製(本框架)過程: 建立->異步繪製->顯示 異步繪製分析:
結論:
pod 'ZJAttributedText'
複製代碼
本框架依賴 SDWebImage (幾乎全部App都集成了, 能夠共用一套緩存邏輯)
內部實現代碼很少, 幾乎全部步驟都添加了註釋, 若是須要學習 CoreText, 異步繪製, 鏈式語法, 還算是個不錯的 Demo, 若是你們感興趣, 能夠補充下 CoreText 相關內容, 這部分網上的資料都比較老, 錯誤也比較多. 歡迎 issue 與 star~