IOS----Core Animation介紹3

原文地址:http://superman474.blog.163.com/blog/static/120661462011857559881/


提供layer內容

  當我們使用cocoa view的子類時,我們要實現drawRect:方法去顯示任何東西。然而CALayer實例經常直接使用,不需子類。因爲CALayer是一個key-value coding兼容的容器類,所以我們可以在任何情況下存儲任意值,去子類化一個CALayer通常是可以避免的。
1.提供CALayer內容
  可以用下面方式之一去指定一個CALayer實例的內容:
  A明確的用一個包含content image的CGImageRef去設置一個layer實例的contents屬性。
  B指定一個代理去提供或者繪畫(draw)content。
  C子類一個CALayer,然後重寫它的display方法。
(1)設置contents屬性
   一個layer的content image可以被指定通過contents屬性(CGImageRef),這可以在layer被創建的時候或者其他任何時候指定。
   下面代碼具體設置一個layer的contents屬性:
CALayer *theLayer; 
  
// create the layer and set the bounds and position 
theLayer=[CALayer layer]; 
theLayer.position=CGPointMake(50.0f,50.0f); 
theLayer.bounds=CGRectMake(0.0f,0.0f,100.0f,100.0f); 
  
// set the contents property to a CGImageRef 
// specified by theImage (loaded elsewhere) 
theLayer.contents=theImage; 

(2)使用代理去提供內容
  我們可以創建一個代理類去實現方法displayLayer: 或者 drawLayer:inContext:去設置layer content image。實現一個代理方法去繪製內容不會自動引起layer用實現的方法去繪製。相反的,我們要明確的告訴layer實例去re-cache內容,通過發送消息setNeedsDisplay 或者setNeedsDisplayInRect:都可以,或者設置屬性needsDisplayOnBoundsChange 爲YES。
  實現方法displayLayer:的代理可以確定對於指定的layer應該去顯示哪一個image,然後設置layer的contents屬性。下面是一個代理實現了displayLayer:
- (void)displayLayer:(CALayer *)theLayer 
{ 
    // check the value of the layer's state key 
    if ([[theLayer valueForKey:@"state"] boolValue]) 
    { 
        // display the yes image 
        theLayer.contents=[someHelperObject loadStateYesImage]; 
    } 
    else { 
        // display the no image 
        theLayer.contents=[someHelperObject loadStateNoImage]; 
    } 
} 

  如果我們必須draw一個layer的內容而不是從一個image加載,我們要去實現代理方法drawLayer:inContext: 。此代理傳遞的參數包括一個請求content的layer和一個CGContextRef去會滑content。
下面就是一個代理實現了drawLayer:inContext:的方法:
- (void)drawLayer:(CALayer *)theLayer 
        inContext:(CGContextRef)theContext 
{ 
    CGMutablePathRef thePath = CGPathCreateMutable(); 
  
    CGPathMoveToPoint(thePath,NULL,15.0f,15.f); 
    CGPathAddCurveToPoint(thePath, 
                          NULL, 
                          15.f,250.0f, 
                          295.0f,250.0f, 
                          295.0f,15.0f); 
  
    CGContextBeginPath(theContext); 
    CGContextAddPath(theContext, thePath ); 
  
    CGContextSetLineWidth(theContext, 
                          [[theLayer valueForKey:@"lineWidth"] floatValue]); 
    CGContextStrokePath(theContext); 
  
    // release the path 
    CFRelease(thePath); 
} 

 (3)通過實現子類去提供CALayer的content
  儘管沒有必要,但是我們yield可以繼承一個CALayer去直接的覆蓋drawing和display方法。當layer需要自定義行爲但是代理不能提供的時候我們用此方法。
  一個CALayer的子類可以重寫display方法,並設置恰當的image給layer的content。如下:
- (void)display 
{ 
    // check the value of the layer's state key 
    if (self.state) 
    { 
        // display the yes image 
        self.contents=[someHelperObject loadStateYesImage]; 
    } 
    else { 
        // display the no image 
        self.contents=[someHelperObject loadStateNoImage]; 
    } 
} 
 一個子類也可以重寫CALayer的drawInContext:方法去draw layer content 在一個graphics context。
- (void)drawInContext:(CGContextRef)theContext 
{ 
    CGMutablePathRef thePath = CGPathCreateMutable(); 
  
    CGPathMoveToPoint(thePath,NULL,15.0f,15.f); 
    CGPathAddCurveToPoint(thePath, 
                          NULL, 
                          15.f,250.0f, 
                          295.0f,250.0f, 
                          295.0f,15.0f); 
  
    CGContextBeginPath(theContext); 
    CGContextAddPath(theContext, thePath ); 
  
    CGContextSetLineWidth(theContext, 
                          self.lineWidth); 
    CGContextSetStrokeColorWithColor(theContext, 
                                     self.lineColor); 
    CGContextStrokePath(theContext); 
    CFRelease(thePath); 
} 
    子類一個CALayer,實現drawing 方法不會自動的去調用drawing。必須明確的去引導實例去re-cache content。通過發送消息setNeedsDisplay或者setNeedsDisplayInRect:都可以,或者設置屬性needsDisplayOnBoundsChange爲YES。
   


2.positioning layer的content。
CALayer提供一個屬性contentsGravity允許我們去position and scale layer的contents image。缺省情況下,content image填充整個layer bounds。忽視自然的圖像縱橫比。
使用contentsGravity positioning常量去具體image的位置,如下圖:
Position constants for a layer’s contentsGravity property

當使用positioning 常量時,contentsCenter屬性將不在使用。


contentsGravity屬性可以被設置爲下面三種來控制其sacle。設置成下列三種時,上面的9種就失效。
Scaling constants for a layer’s contentsGravity property

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章