CoreAnimation编程指南(五)图层内容
生活随笔
收集整理的這篇文章主要介紹了
CoreAnimation编程指南(五)图层内容
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
當(dāng)我們使用Cocoa的視圖的時(shí)候,我們必須繼承NSView或者UIView并且重載函數(shù)drawRect:來顯示任何內(nèi)容。但是CALayer實(shí)例可以直接使用,而無需繼承子類。因?yàn)镃ALayer是一個鍵-值編碼兼容的容器類,你可以在實(shí)例里面存儲任意值,所以子類實(shí)例化完全可以避免。
1.1 給CALayer提供內(nèi)容
? 你可以通過以下任何一種方法指定CALayer實(shí)例的內(nèi)容: ? (1)使用包含圖片內(nèi)容的CGImageRef來顯式的設(shè)置圖層的contents的屬性。 ? (2)指定一個委托,它提供或者重繪內(nèi)容。 ? (3)繼承CALayer類重載顯示的函數(shù)。
1.1.1 設(shè)置contents屬性
? 圖層的圖片內(nèi)容可以通過指定contents屬性的值為CGImageRef。當(dāng)圖層被創(chuàng)建的時(shí)候或者在任何其他時(shí)候,這個操作可以在其他實(shí)體上面完成(如表3所示)。? ? 代碼 1 設(shè)定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; ? 1.1.2 通過委托提供內(nèi)容
? 你可以繪制圖層的內(nèi)容,或更好的封裝圖層的內(nèi)容圖片,通過創(chuàng)建一個委托類實(shí)現(xiàn)下列方法之一: ? displayLayer:或drawLayer:inContext: ?? ? 實(shí)現(xiàn)委托重繪的方法并不意味會自動的觸發(fā)圖層使用實(shí)現(xiàn)的方法來重繪內(nèi)容。而是你要顯式的告訴一個圖層實(shí)例來重新緩存內(nèi)容,通過發(fā)送以下任何一個方法setNeedsDisplay或者setNeedsDisplayInRect:的消息,或者把圖層的needsDisplayOnBoundsChange屬性值設(shè)置為YES。 ?? ? 通過委托實(shí)現(xiàn)方法displayLayer:可以根據(jù)特定的圖層決定顯示什么圖片,還可以更加需要設(shè)置圖層的contents屬性值。下面的例子是“圖層的坐標(biāo)系”部分的,它實(shí)現(xiàn)displayerLayer:方法根據(jù)state的值設(shè)置theLayer的contents屬性。子類不需要存儲state的值,因?yàn)镃ALayer的實(shí)例是一個鍵-值編碼容器。
? 代碼 2 ?委托方法displayLayer:的實(shí)現(xiàn)示例 ? - (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]; ? ? ? } ? } ? ? 如果你必須重繪圖層的內(nèi)容,而不是通過加載圖片,那你需要實(shí)現(xiàn)drawLayer:inContext:方法。通過委托可以決定哪些內(nèi)容是需要的并使用CGContextRef來重繪內(nèi)容。
? 下面的例子是“指定圖層的幾何”部分內(nèi)容,它實(shí)現(xiàn)了drawLayer:inContext:方法使用lineWidth鍵值來重繪一個路徑(path),返回therLayer。 ? ? 代碼 3 ?代理方法drawLayer:inContext:的實(shí)現(xiàn)示例 ? - (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); ? } ? 1.1.3 通過子類提供圖層的內(nèi)容
? 雖然通常情況不需要這樣做,但是你仍可以繼承CALayer直接重載重繪和顯示方法。這個通常發(fā)生在你的圖層需要定制行為而委托又無法滿足需求的時(shí)候。
? 子類可以重載CALayer的顯示方法,設(shè)置圖層的內(nèi)容為適當(dāng)?shù)膱D片。下面的例子是“變換圖層的幾何”部分的內(nèi)容,它提供了和“圖層的坐標(biāo)系”例子相同的功能。不同的是子類定義state為實(shí)例的屬性,而不是根據(jù)CALayer的鍵-值編碼容器獲取。 ? ? 代碼 4 ?CALayer display 方法的覆蓋示例 ? - (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:繪制圖層的內(nèi)容到一個圖形上下文。下面的例子是“修改變換的數(shù)據(jù)結(jié)構(gòu)”的內(nèi)容,它和“指定圖層的幾何”里面實(shí)現(xiàn)委托的辦法一樣產(chǎn)生相同的圖片內(nèi)容。唯一的不同的是實(shí)現(xiàn)委托里面的lineWidth和lineColor現(xiàn)在是子類實(shí)例的屬性。
? Listing 5 ?覆蓋layer的drawInContext:方法示例 ? - (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并且實(shí)現(xiàn)其中的重繪方法并不意味重繪會自動發(fā)生。你必須顯式的促使實(shí)例重新緩存其內(nèi)容,可以通過發(fā)送以下任何一個方法setNeedsDisplay或setNeedsDisplayInRect:的消息,亦或者設(shè)置圖層的needsDisplaOnBoundsChange屬性為YES。 ? 1.2 修改圖層內(nèi)容的位置
? CALayer的屬性contentsGravity允許你在圖層的邊界內(nèi)容修改圖層的contents圖片的位置或者伸縮值。默認(rèn)情況下,內(nèi)容的圖像完全填充層的邊界,忽視自然的圖像寬高比。
? 使用contentsGravity位置常量,你可以指定圖片位于圖層任何一個邊界,比如位于圖層的角落,或者圖層邊界的中心。然而當(dāng)你使用位置常量的時(shí)候,contentsCenter屬性會被忽略。表1列舉了位置常量和他們相應(yīng)的位置。 ? ? ? layer的contentsGravity屬性的定位常量 ? kCAGravityTopLeft ? ? Positions the content image in the top left corner of the layer. ? kCAGravityTop ? ? Positions the content image horizontally centered along the top edge of the layer. ? kCAGravityTopRight ? ? Positions the content image in the top right corner of the layer. ? kCAGravityLeft ? ? Positions the content image vertically centered on the left edge of the layer. ? kCAGravityCenter ? ? Positions the content image at the center of the layer. ? kCAGravityRight ? ? Positions the content image vertically centered on the right edge of the layer. ? kCAGravityBottomLeft ? ? Positions the content image in the bottom left corner of the layer. ? kCAGravityBottom ? ? Positions the content image centered along the bottom edge of the layer.? ? kCAGravityBottomRight ? ? Positions the content image in the top right corner of the layer. ? ? “圖層的坐標(biāo)系”標(biāo)識了所支持的內(nèi)容位置和他們相應(yīng)的常量。 ? 圖 1 ?layer的contentsGravity屬性的定位常量 ? ? ? ? ? 通過設(shè)置contentsGravity屬性為其他一個常量(如表2所示)。圖層的內(nèi)容圖片可以被向上或者向下拉伸, 僅當(dāng)使用其他任何一個調(diào)整大小的常量的時(shí)候,contentsCenter屬性才會對內(nèi)容圖片起作用。 ? ? 表 2 ?Layer的 contentsGravity 屬性的縮放常量 ? kCAGravityResize ? ? Resize the content image to completely fill the layer bounds, potentially ignoring the natural aspect of the content. This is the default. ? kCAGravityResizeAspect ? ? Resize the content image to scale such that it is displayed as large as possible within the layer bounds, yet still retains its natural aspect. ? kCAGravityResizeAspectFill ? ? Resize the content image to scale such that it is displayed filling the layer bounds, yet retaining its natural aspect. This may cause the content to extend outside the layer bounds.
? “變換圖層的幾何”演示了如何使用調(diào)整大小的模式來調(diào)整一個正方形圖像的大小讓其適應(yīng)圖層的方形邊界。 ? 圖 2 ?Layer的 contentsGravity 屬性的縮放常量 ? ? ?? ? ? 注意:使用任何常量kCAGravityResize、kCAGravityResizeAspect和kCAGravityResizeAspectFill和表1中的重心位置常量無關(guān)。圖層的內(nèi)容將會填充整個邊界,所以使用這些常量無法改變圖層內(nèi)容的位置。
轉(zhuǎn)自夢維:http://www.dreamingwish.com/dream-2012/coreanimation-programming-guide-e-the-content-layer.html
1.1 給CALayer提供內(nèi)容
? 你可以通過以下任何一種方法指定CALayer實(shí)例的內(nèi)容: ? (1)使用包含圖片內(nèi)容的CGImageRef來顯式的設(shè)置圖層的contents的屬性。 ? (2)指定一個委托,它提供或者重繪內(nèi)容。 ? (3)繼承CALayer類重載顯示的函數(shù)。
1.1.1 設(shè)置contents屬性
? 圖層的圖片內(nèi)容可以通過指定contents屬性的值為CGImageRef。當(dāng)圖層被創(chuàng)建的時(shí)候或者在任何其他時(shí)候,這個操作可以在其他實(shí)體上面完成(如表3所示)。? ? 代碼 1 設(shè)定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; ? 1.1.2 通過委托提供內(nèi)容
? 你可以繪制圖層的內(nèi)容,或更好的封裝圖層的內(nèi)容圖片,通過創(chuàng)建一個委托類實(shí)現(xiàn)下列方法之一: ? displayLayer:或drawLayer:inContext: ?? ? 實(shí)現(xiàn)委托重繪的方法并不意味會自動的觸發(fā)圖層使用實(shí)現(xiàn)的方法來重繪內(nèi)容。而是你要顯式的告訴一個圖層實(shí)例來重新緩存內(nèi)容,通過發(fā)送以下任何一個方法setNeedsDisplay或者setNeedsDisplayInRect:的消息,或者把圖層的needsDisplayOnBoundsChange屬性值設(shè)置為YES。 ?? ? 通過委托實(shí)現(xiàn)方法displayLayer:可以根據(jù)特定的圖層決定顯示什么圖片,還可以更加需要設(shè)置圖層的contents屬性值。下面的例子是“圖層的坐標(biāo)系”部分的,它實(shí)現(xiàn)displayerLayer:方法根據(jù)state的值設(shè)置theLayer的contents屬性。子類不需要存儲state的值,因?yàn)镃ALayer的實(shí)例是一個鍵-值編碼容器。
? 代碼 2 ?委托方法displayLayer:的實(shí)現(xiàn)示例 ? - (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]; ? ? ? } ? } ? ? 如果你必須重繪圖層的內(nèi)容,而不是通過加載圖片,那你需要實(shí)現(xiàn)drawLayer:inContext:方法。通過委托可以決定哪些內(nèi)容是需要的并使用CGContextRef來重繪內(nèi)容。
? 下面的例子是“指定圖層的幾何”部分內(nèi)容,它實(shí)現(xiàn)了drawLayer:inContext:方法使用lineWidth鍵值來重繪一個路徑(path),返回therLayer。 ? ? 代碼 3 ?代理方法drawLayer:inContext:的實(shí)現(xiàn)示例 ? - (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); ? } ? 1.1.3 通過子類提供圖層的內(nèi)容
? 雖然通常情況不需要這樣做,但是你仍可以繼承CALayer直接重載重繪和顯示方法。這個通常發(fā)生在你的圖層需要定制行為而委托又無法滿足需求的時(shí)候。
? 子類可以重載CALayer的顯示方法,設(shè)置圖層的內(nèi)容為適當(dāng)?shù)膱D片。下面的例子是“變換圖層的幾何”部分的內(nèi)容,它提供了和“圖層的坐標(biāo)系”例子相同的功能。不同的是子類定義state為實(shí)例的屬性,而不是根據(jù)CALayer的鍵-值編碼容器獲取。 ? ? 代碼 4 ?CALayer display 方法的覆蓋示例 ? - (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:繪制圖層的內(nèi)容到一個圖形上下文。下面的例子是“修改變換的數(shù)據(jù)結(jié)構(gòu)”的內(nèi)容,它和“指定圖層的幾何”里面實(shí)現(xiàn)委托的辦法一樣產(chǎn)生相同的圖片內(nèi)容。唯一的不同的是實(shí)現(xiàn)委托里面的lineWidth和lineColor現(xiàn)在是子類實(shí)例的屬性。
? Listing 5 ?覆蓋layer的drawInContext:方法示例 ? - (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并且實(shí)現(xiàn)其中的重繪方法并不意味重繪會自動發(fā)生。你必須顯式的促使實(shí)例重新緩存其內(nèi)容,可以通過發(fā)送以下任何一個方法setNeedsDisplay或setNeedsDisplayInRect:的消息,亦或者設(shè)置圖層的needsDisplaOnBoundsChange屬性為YES。 ? 1.2 修改圖層內(nèi)容的位置
? CALayer的屬性contentsGravity允許你在圖層的邊界內(nèi)容修改圖層的contents圖片的位置或者伸縮值。默認(rèn)情況下,內(nèi)容的圖像完全填充層的邊界,忽視自然的圖像寬高比。
? 使用contentsGravity位置常量,你可以指定圖片位于圖層任何一個邊界,比如位于圖層的角落,或者圖層邊界的中心。然而當(dāng)你使用位置常量的時(shí)候,contentsCenter屬性會被忽略。表1列舉了位置常量和他們相應(yīng)的位置。 ? ? ? layer的contentsGravity屬性的定位常量 ? kCAGravityTopLeft ? ? Positions the content image in the top left corner of the layer. ? kCAGravityTop ? ? Positions the content image horizontally centered along the top edge of the layer. ? kCAGravityTopRight ? ? Positions the content image in the top right corner of the layer. ? kCAGravityLeft ? ? Positions the content image vertically centered on the left edge of the layer. ? kCAGravityCenter ? ? Positions the content image at the center of the layer. ? kCAGravityRight ? ? Positions the content image vertically centered on the right edge of the layer. ? kCAGravityBottomLeft ? ? Positions the content image in the bottom left corner of the layer. ? kCAGravityBottom ? ? Positions the content image centered along the bottom edge of the layer.? ? kCAGravityBottomRight ? ? Positions the content image in the top right corner of the layer. ? ? “圖層的坐標(biāo)系”標(biāo)識了所支持的內(nèi)容位置和他們相應(yīng)的常量。 ? 圖 1 ?layer的contentsGravity屬性的定位常量 ? ? ? ? ? 通過設(shè)置contentsGravity屬性為其他一個常量(如表2所示)。圖層的內(nèi)容圖片可以被向上或者向下拉伸, 僅當(dāng)使用其他任何一個調(diào)整大小的常量的時(shí)候,contentsCenter屬性才會對內(nèi)容圖片起作用。 ? ? 表 2 ?Layer的 contentsGravity 屬性的縮放常量 ? kCAGravityResize ? ? Resize the content image to completely fill the layer bounds, potentially ignoring the natural aspect of the content. This is the default. ? kCAGravityResizeAspect ? ? Resize the content image to scale such that it is displayed as large as possible within the layer bounds, yet still retains its natural aspect. ? kCAGravityResizeAspectFill ? ? Resize the content image to scale such that it is displayed filling the layer bounds, yet retaining its natural aspect. This may cause the content to extend outside the layer bounds.
? “變換圖層的幾何”演示了如何使用調(diào)整大小的模式來調(diào)整一個正方形圖像的大小讓其適應(yīng)圖層的方形邊界。 ? 圖 2 ?Layer的 contentsGravity 屬性的縮放常量 ? ? ?? ? ? 注意:使用任何常量kCAGravityResize、kCAGravityResizeAspect和kCAGravityResizeAspectFill和表1中的重心位置常量無關(guān)。圖層的內(nèi)容將會填充整個邊界,所以使用這些常量無法改變圖層內(nèi)容的位置。
轉(zhuǎn)自夢維:http://www.dreamingwish.com/dream-2012/coreanimation-programming-guide-e-the-content-layer.html
總結(jié)
以上是生活随笔為你收集整理的CoreAnimation编程指南(五)图层内容的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea端口占用解决记录
- 下一篇: spring-boot 一款无侵入型,轻