<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # CATextLayer 用戶界面是無法從一個單獨的圖片里面構建的。一個設計良好的圖標能夠很好地表現一個按鈕或控件的意圖,不過你遲早都要需要一個不錯的老式風格的文本標簽。 如果你想在一個圖層里面顯示文字,完全可以借助圖層代理直接將字符串使用Core Graphics寫入圖層的內容(這就是UILabel的精髓)。如果越過寄宿于圖層的視圖,直接在圖層上操作,那其實相當繁瑣。你要為每一個顯示文字的圖層創建一個能像圖層代理一樣工作的類,還要邏輯上判斷哪個圖層需要顯示哪個字符串,更別提還要記錄不同的字體,顏色等一系列亂七八糟的東西。 萬幸的是這些都是不必要的,Core Animation提供了一個`CALayer`的子類`CATextLayer`,它以圖層的形式包含了`UILabel`幾乎所有的繪制特性,并且額外提供了一些新的特性。 同樣,`CATextLayer`也要比`UILabel`渲染得快得多。很少有人知道在iOS 6及之前的版本,`UILabel`其實是通過WebKit來實現繪制的,這樣就造成了當有很多文字的時候就會有極大的性能壓力。而`CATextLayer`使用了Core text,并且渲染得非常快。 讓我們來嘗試用`CATextLayer`來顯示一些文字。清單6.2的代碼實現了這一功能,結果如圖6.2所示。 清單6.2 用`CATextLayer`來實現一個`UILabel` ~~~ @interface ViewController () @property (nonatomic, weak) IBOutlet UIView *labelView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //create a text layer CATextLayer *textLayer = [CATextLayer layer]; textLayer.frame = self.labelView.bounds; [self.labelView.layer addSublayer:textLayer]; //set text attributes textLayer.foregroundColor = [UIColor blackColor].CGColor; textLayer.alignmentMode = kCAAlignmentJustified; textLayer.wrapped = YES; //choose a font UIFont *font = [UIFont systemFontOfSize:15]; //set layer font CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFontRef fontRef = CGFontCreateWithFontName(fontName); textLayer.font = fontRef; textLayer.fontSize = font.pointSize; CGFontRelease(fontRef); //choose some text NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis"; //set layer text textLayer.string = text; } @end ~~~ ![](https://box.kancloud.cn/2015-12-24_567bc1ffe9895.png) 圖6.2 用`CATextLayer`來顯示一個純文本標簽 如果你仔細看這個文本,你會發現一個奇怪的地方:這些文本有一些像素化了。這是因為并沒有以Retina的方式渲染,第二章提到了這個`contentScale`屬性,用來決定圖層內容應該以怎樣的分辨率來渲染。`contentsScale`并不關心屏幕的拉伸因素而總是默認為1.0。如果我們想以Retina的質量來顯示文字,我們就得手動地設置`CATextLayer`的`contentsScale`屬性,如下: ~~~ textLayer.contentsScale = [UIScreen mainScreen].scale; ~~~ 這樣就解決了這個問題(如圖6.3) ![](https://box.kancloud.cn/2015-12-24_567bc2001e454.png) 圖6.3 設置`contentsScale`來匹配屏幕 `CATextLayer`的`font`屬性不是一個`UIFont`類型,而是一個`CFTypeRef`類型。這樣可以根據你的具體需要來決定字體屬性應該是用`CGFontRef`類型還是`CTFontRef`類型(Core Text字體)。同時字體大小也是用`fontSize`屬性單獨設置的,因為`CTFontRef`和`CGFontRef`并不像UIFont一樣包含點大小。這個例子會告訴你如何將`UIFont`轉換成`CGFontRef`。 另外,`CATextLayer`的`string`屬性并不是你想象的`NSString`類型,而是`id`類型。這樣你既可以用`NSString`也可以用`NSAttributedString`來指定文本了(注意,`NSAttributedString`并不是`NSString`的子類)。屬性化字符串是iOS用來渲染字體風格的機制,它以特定的方式來決定指定范圍內的字符串的原始信息,比如字體,顏色,字重,斜體等。 ## 富文本 iOS 6中,Apple給`UILabel`和其他UIKit文本視圖添加了直接的屬性化字符串的支持,應該說這是一個很方便的特性。不過事實上從iOS3.2開始`CATextLayer`就已經支持屬性化字符串了。這樣的話,如果你想要支持更低版本的iOS系統,`CATextLayer`無疑是你向界面中增加富文本的好辦法,而且也不用去跟復雜的Core Text打交道,也省了用`UIWebView`的麻煩。 讓我們編輯一下示例使用到`NSAttributedString`(見清單6.3).iOS 6及以上我們可以用新的`NSTextAttributeName`實例來設置我們的字符串屬性,但是練習的目的是為了演示在iOS 5及以下,所以我們用了Core Text,也就是說你需要把Core Text framework添加到你的項目中。否則,編譯器是無法識別屬性常量的。 圖6.4是代碼運行結果(注意那個紅色的下劃線文本) 清單6.3 用NSAttributedString實現一個富文本標簽。 ~~~ #import "DrawingView.h" #import #import @interface ViewController () @property (nonatomic, weak) IBOutlet UIView *labelView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //create a text layer CATextLayer *textLayer = [CATextLayer layer]; textLayer.frame = self.labelView.bounds; textLayer.contentsScale = [UIScreen mainScreen].scale; [self.labelView.layer addSublayer:textLayer]; //set text attributes textLayer.alignmentMode = kCAAlignmentJustified; textLayer.wrapped = YES; //choose a font UIFont *font = [UIFont systemFontOfSize:15]; //choose some text NSString *text = @"Lorem ipsum dolor sit amet, consectetur adipiscing \ elit. Quisque massa arcu, eleifend vel varius in, facilisis pulvinar \ leo. Nunc quis nunc at mauris pharetra condimentum ut ac neque. Nunc \ elementum, libero ut porttitor dictum, diam odio congue lacus, vel \ fringilla sapien diam at purus. Etiam suscipit pretium nunc sit amet \ lobortis"; ? //create attributed string NSMutableAttributedString *string = nil; string = [[NSMutableAttributedString alloc] initWithString:text]; //convert UIFont to a CTFont CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFloat fontSize = font.pointSize; CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL); //set text attributes NSDictionary *attribs = @{ (__bridge id)kCTForegroundColorAttributeName:(__bridge id)[UIColor blackColor].CGColor, (__bridge id)kCTFontAttributeName: (__bridge id)fontRef }; [string setAttributes:attribs range:NSMakeRange(0, [text length])]; attribs = @{ (__bridge id)kCTForegroundColorAttributeName: (__bridge id)[UIColor redColor].CGColor, (__bridge id)kCTUnderlineStyleAttributeName: @(kCTUnderlineStyleSingle), (__bridge id)kCTFontAttributeName: (__bridge id)fontRef }; [string setAttributes:attribs range:NSMakeRange(6, 5)]; //release the CTFont we created earlier CFRelease(fontRef); //set layer text textLayer.string = string; } @end ~~~ ![](https://box.kancloud.cn/2015-12-24_567bc2004ee98.png) 圖6.4 用CATextLayer實現一個富文本標簽。 ## 行距和字距 有必要提一下的是,由于繪制的實現機制不同(Core Text和WebKit),用`CATextLayer`渲染和用`UILabel`渲染出的文本行距和字距也不是不盡相同的。 二者的差異程度(由使用的字體和字符決定)總的來說挺小,但是如果你想正確的顯示普通便簽和`CATextLayer`就一定要記住這一點。 ##UILabel的替代品 我們已經證實了`CATextLayer`比`UILabel`有著更好的性能表現,同時還有額外的布局選項并且在iOS 5上支持富文本。但是與一般的標簽比較而言會更加繁瑣一些。如果我們真的在需求一個`UILabel`的可用替代品,最好是能夠在Interface Builder上創建我們的標簽,而且盡可能地像一般的視圖一樣正常工作。 我們應該繼承`UILabel`,然后添加一個子圖層`CATextLayer`并重寫顯示文本的方法。但是仍然會有由`UILabel`的`-drawRect:`方法創建的空寄宿圖。而且由于`CALayer`不支持自動縮放和自動布局,子視圖并不是主動跟蹤視圖邊界的大小,所以每次視圖大小被更改,我們不得不手動更新子圖層的邊界。 我們真正想要的是一個用`CATextLayer`作為宿主圖層的`UILabel`子類,這樣就可以隨著視圖自動調整大小而且也沒有冗余的寄宿圖啦。 就像我們在第一章『圖層樹』討論的一樣,每一個`UIView`都是寄宿在一個`CALayer`的示例上。這個圖層是由視圖自動創建和管理的,那我們可以用別的圖層類型替代它么?一旦被創建,我們就無法代替這個圖層了。但是如果我們繼承了`UIView`,那我們就可以重寫`+layerClass`方法使得在創建的時候能返回一個不同的圖層子類。`UIView`會在初始化的時候調用`+layerClass`方法,然后用它的返回類型來創建宿主圖層。 清單6.4 演示了一個`UILabel`子類`LayerLabel`用`CATextLayer`繪制它的問題,而不是調用一般的`UILabel`使用的較慢的`-drawRect:`方法。`LayerLabel`示例既可以用代碼實現,也可以在Interface Builder實現,只要把普通的標簽拖入視圖之中,然后設置它的類是LayerLabel就可以了。 清單6.4 使用`CATextLayer`的`UILabel`子類:`LayerLabel` ~~~ #import "LayerLabel.h" #import @implementation LayerLabel + (Class)layerClass { //this makes our label create a CATextLayer //instead of a regular CALayer for its backing layer return [CATextLayer class]; } - (CATextLayer *)textLayer { return (CATextLayer *)self.layer; } - (void)setUp { //set defaults from UILabel settings self.text = self.text; self.textColor = self.textColor; self.font = self.font; //we should really derive these from the UILabel settings too //but that's complicated, so for now we'll just hard-code them [self textLayer].alignmentMode = kCAAlignmentJustified; ? [self textLayer].wrapped = YES; [self.layer display]; } - (id)initWithFrame:(CGRect)frame { //called when creating label programmatically if (self = [super initWithFrame:frame]) { [self setUp]; } return self; } - (void)awakeFromNib { //called when creating label using Interface Builder [self setUp]; } - (void)setText:(NSString *)text { super.text = text; //set layer text [self textLayer].string = text; } - (void)setTextColor:(UIColor *)textColor { super.textColor = textColor; //set layer text color [self textLayer].foregroundColor = textColor.CGColor; } - (void)setFont:(UIFont *)font { super.font = font; //set layer font CFStringRef fontName = (__bridge CFStringRef)font.fontName; CGFontRef fontRef = CGFontCreateWithFontName(fontName); [self textLayer].font = fontRef; [self textLayer].fontSize = font.pointSize; ? CGFontRelease(fontRef); } @end ~~~ 如果你運行代碼,你會發現文本并沒有像素化,而我們也沒有設置`contentsScale`屬性。把`CATextLayer`作為宿主圖層的另一好處就是視圖自動設置了`contentsScale`屬性。 在這個簡單的例子中,我們只是實現了`UILabel`的一部分風格和布局屬性,不過稍微再改進一下我們就可以創建一個支持`UILabel`所有功能甚至更多功能的`LayerLabel`類(你可以在一些線上的開源項目中找到)。 如果你打算支持iOS 6及以上,基于`CATextLayer`的標簽可能就有有些局限性。但是總得來說,如果想在app里面充分利用`CALayer`子類,用`+layerClass`來創建基于不同圖層的視圖是一個簡單可復用的方法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看