YYText 源碼解析 —— YYLabel (一)

架構(gòu)


(引用作者框架對比圖片)

YYText包括控件(YYLabel,YYTextView),布局(YYTextLayout,NSAttributedString,YYTextContainer),核心(CoreText)。

源碼目錄組織

YYLabel

繼承關(guān)系


YYLabel 直接繼承 UIView,作者自己實(shí)現(xiàn) Label 的渲染。+_+

state

struct {
            
// 是否需要更新布局
unsigned int layoutNeedUpdate : 1;
unsigned int showingHighlight : 1;

unsigned int trackingTouch : 1;
unsigned int swallowTouch : 1;
unsigned int touchMoved : 1;

unsigned int hasTapAction : 1;
unsigned int hasLongPressAction : 1;

// 內(nèi)容是否支持逐漸消失
unsigned int contentsNeedFade : 1;
    } _state;

如何熏染出 Text

YYLabel 的熏染是通過 YYTextAsyncLayerDelegate 完成。 YYTextAsyncLayerDelegate 提供了 newAsyncDisplayTask 配置方法用來實(shí)現(xiàn)渲染。

YYTextAsyncLayer 與 YYLabel 的熏染流程

setText 為例,看看這個(gè)熏染的流程。

  • [self.layer setNeedsDisplay] 這里調(diào)用的是 YYTextAsyncLayersetNeedsDisplay 。因?yàn)?layerClass 方法被重寫了,返回了 YYTextAsyncLayer 。所以主layer所使用的類是 YYTextAsyncLayer
  • _cancelAsyncDisplay 的實(shí)現(xiàn),后續(xù)再探討。。。記遺留問題。
  • 這里 display 也被重寫了,在這了執(zhí)行了渲染最為關(guān)鍵的函數(shù) _displayAsync 。
  • YYTextAsyncLayer 提供了 displaysAsynchronously 用來控制是否進(jìn)行異步渲染,默認(rèn)為異步熏染。

熏染

本人對 Core Graphics Framework 部分不同熟悉,個(gè)人重點(diǎn)對這一塊代碼進(jìn)行學(xué)。剛才我們發(fā)現(xiàn)這里的渲染分為:普通渲染(ps:不知道怎么稱,叫同步渲染感覺不太適合,就叫普通渲染吧)和異步渲染。這兩種渲染的渲染代碼處理基本是一樣的,只是異步熏染增加了一些多線程的處理的考慮(比如:多線程經(jīng)典的“讀與寫”的問題)。

所以就直接學(xué)習(xí)普通渲染部分的代碼吧#^_^#

YYTextAsyncLayer 熏染學(xué)習(xí)

UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale);
CGContextRef context = UIGraphicsGetCurrentContext();

if (self.opaque) {
    CGSize size = self.bounds.size;
    size.width *= self.contentsScale;
    size.height *= self.contentsScale;
    CGContextSaveGState(context); {
        if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) {
            CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
            CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
            CGContextFillPath(context);
        }
        if (self.backgroundColor) {
            CGContextSetFillColorWithColor(context, self.backgroundColor);
            CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
            CGContextFillPath(context);
        }
    } CGContextRestoreGState(context);
}

task.display(context, self.bounds.size, ^{return NO;});
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.contents = (__bridge id)(image.CGImage);
  • 開始是調(diào)用 UIGraphicsBeginImageContextWithOptions 創(chuàng)建一個(gè)圖片處理的上下文。 繪制結(jié)束調(diào)用 UIGraphicsEndImageContext
  • 通過 UIGraphicsGetCurrentContext 獲取當(dāng)前圖形的上下文。
  • 這里有個(gè) opaque 屬性表示是否不透明,詳細(xì)屬性參見。
  • CGContextSaveGState 把上下文保存到棧中。然后通過 CGContextSetFillColorWithColor 設(shè)置填充顏色, CGContextAddRect 添加矩形,CGContextFillPath 填充上下文路徑。 最后保存通過 CGContextRestoreGState 保存最近的上下文。
  • 調(diào)用 task.display 回調(diào),這里是調(diào)用配置的渲染方法,后面再分析 YYLabel 的熏染回調(diào)。 YYLabel 的熏染主要通過 YYTextLayout 來處理。 這么后續(xù)再做學(xué)習(xí)。
  • 通過 UIGraphicsGetImageFromCurrentImageContext 當(dāng)前的上下文繪制出來的圖片,結(jié)束繪制。
  • 最后將圖片賦值給 contents 屬性完成熏染。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載:http://www.itdecent.cn/p/32fcadd12108 每個(gè)UIView有一個(gè)伙伴稱為l...
    F麥子閱讀 6,567評論 0 13
  • 每個(gè)UIView有一個(gè)伙伴稱為layer,一個(gè)CALayer。UIView實(shí)際上并沒有把自己畫到屏幕上;它繪制本身...
    shenzhenboy閱讀 3,252評論 0 17
  • 卷首語 歡迎來到 objc.io 的第三期! 這一期都是關(guān)于視圖層的。當(dāng)然視圖層有很多方面,我們需要把它們縮小到幾...
    評評分分閱讀 1,930評論 0 18
  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個(gè)像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,756評論 0 7
  • 教育孩子是世界上最復(fù)雜的事情 《清單革命》中將教育孩子列為最復(fù)雜的事情,這就是說,我一直持有的觀點(diǎn)跟高人不謀而合。...
    跑步者2008閱讀 90評論 0 1

友情鏈接更多精彩內(nèi)容