Core Animation - 6
来源:互联网 发布:淘宝卖家从哪里登陆 编辑:程序博客网 时间:2024/06/05 14:36
Layer Trees Reflect Different Aspects of the Animation State
An app using Core Animation has three sets of layer objects. Each set of layer objects has a different role in making the content of your app appear onscreen:
- Objects in the model layer tree (or simply “layer tree”) are the ones your app interacts with the most. The objects in this tree are the model objects that store the target values for any animations. Whenever you change the property of a layer, you use one of these objects.
- Objects in the presentation tree contain the in-flight values for any running animations. Whereas the layer tree objects contain the target values for an animation, the objects in the presentation tree reflect the current values as they appear onscreen. You should never modify the objects in this tree. Instead, you use these objects to read current animation values, perhaps to create a new animation starting at those values.
- Objects in the render tree perform the actual animations and are private to Core Animation.
Each set of layer objects is organized into a hierarchical structure like the views in your app. In fact, for an app that enables layers for all of its views, the initial structure of each tree matches the structure of the view hierarchy exactly. However, an app can add additional layer objects—that is, layers not associated with a view—into the layer hierarchy as needed. You might do this in situations to optimize your app’s performance for content that does not require all the overhead of a view. Figure 1-9 shows the breakdown of layers found in a simple iOS app. The window in the example contains a content view, which itself contains a button view and two standalone layer objects. Each view has a corresponding layer object that forms part of the layer hierarchy.
官方文档指出了三个层树,分别是: model layer tree , presentation tree , render tree 。 模型树,呈现树,渲染树。The Relationship Between Layers and Views
Changing the Layer Object Associated with a View
Layer-backed views create an instance of the CALayer class by default, and in most cases you might not need a different type of layer object. However, Core Animation provides different layer classes, each of which provides specialized capabilities that you might find useful. Choosing a different layer class might enable you to improve performance or support a specific type of content in a simple way. For example, theCATiledLayer class is optimized for displaying large images in an efficient manner.Changing the Layer Class Used by UIView
You can change the type of layer used by an iOS view by overriding the view’s layerClass method and returning a different class object. Most iOS views create a CALayer object and use that layer as the backing store for its content. For most of your own views, this default choice is a good one and you should not need to change it. But you might find that a different layer class is more appropriate in certain situations. For example, you might want to change the layer class in the following situations:
+ (Class)layerClass; // default is [CALayer class]. Used when creating the underlying layer for the view.默认返回[CALayer class],你可以修改层的类型使用重载这个方法并且会相应地返回一个不同的类对象。但大多数的视图对象是不会去修改的,注意这个underlying,使用这个方法所修改的层对象就是层继承树的根部层容器,你可以修改默认层由于以下的几种情况:
- Your view draws content using Metal or OpenGL ES, in which case you would use a CAMetalLayer or CAEAGLLayer object.
- There is a specialized layer class that offers better performance.
- You want to take advantage of some specialized Core Animation layer classes, such as particle emitters or replicators.
Changing the layer class of a view is very straightforward; an example is shown in Listing 2-1. All you have to do is override thelayerClass method and return the class object you want to use instead. Prior to display, the view calls thelayerClass method and uses the returned class to create a new layer object for itself. Once created, a view’s layer object cannot be changed.
修改层类非常简单,并且在视图显示之前会执行这个方法,一旦创建,无法改变哦/** 返回一个CAMetalLayer类 **/ /** 把默认的底层层类修改了 **/ + (Class) layerClass { return [CAMetalLayer class]; }类似操作的类有一下那么多:
Providing a Layer’s Contents
Layers are data objects that manage content provided by your app. A layer’s content consists of a bitmap containing the visual data you want to display. You can provide the content for that bitmap in one of three ways:- Assign an image object directly to the layer object’s contents property. (This technique is best for layer content that never, or rarely, changes.)
- Assign a delegate object to the layer and let the delegate draw the layer’s content. (This technique is best for layer content that might change periodically and can be provided by an external object, such as a view.)
- Define a layer subclass and override one of its drawing methods to provide the layer contents yourself. (This technique is appropriate if you have to create a custom layer subclass anyway or if you want to change the fundamental drawing behavior of the layer.)
/** Layer content properties and methods. **//* An object providing the contents of the layer, typically a CGImageRef, * but may be something else. (For example, NSImage objects are * supported on Mac OS X 10.6 and later.) Default value is nil. * Animatable. */@property(strong) id contents;
3.定义个层的子类并且重载它部分或全部的绘图方法来自身地提供层对象(这种方法对于你想要创建一个自定义的子层对象或者你想要修改层的基本绘图方法)
Using an Image for the Layer’s Content
Because a layer is just a container for managing a bitmap image,you can assign an image directly to the layer’s contents property. Assigning an image to the layer is easy and lets you specify the exact image you want to display onscreen. The layer uses the image object you provide directly and does not attempt to create its own copy of that image. This behavior can save memory in cases where your app uses the same image in multiple places.The image you assign to a layer must be a CGImageRef type. (In OS X v10.6 and later, you can also assign an NSImage object.) When assigning images, remember to provide an image whose resolution matches the resolution of the native device. For devices with Retina displays, this might also require you to adjust the contentsScale property of the image. For information on using high-resolution content with your layers, see Working with High-Resolution Images.
Using a Delegate to Provide the Layer’s Content
If the content of your layer changes dynamically, you can use a delegate object to provide and update that content when needed. At display time, the layer calls the methods of your delegate to provide the needed content:
- If your delegate implements the displayLayer: method, that implementation is responsible for creating a bitmap and assigning it to the layer’s contents property.
- If your delegate implements the drawLayer:inContext: method, Core Animation creates a bitmap, creates a graphics context to draw into that bitmap, and then calls your delegate method to fill the bitmap. All your delegate method has to do is draw into the provided graphics context.
The delegate object must implement either the displayLayer: ordrawLayer:inContext: method. If the delegate implements both thedisplayLayer: and drawLayer:inContext:method, the layer calls only thedisplayLayer: method.
委托对象必须实现上面提及的两个方法中的其中一种,但是如果两个都实现了,只会调用diaplayLayer:方法。- (void)displayLayer:(CALayer *)theLayer { // Check the value of some state property if (self.displayYesImage) { // Display the Yes image theLayer.contents = [someHelperObject loadStateYesImage]; } else { // Display the No image theLayer.contents = [someHelperObject loadStateNoImage]; }}
If you do not have prerendered images or a helper object to create bitmaps for you, your delegate can draw the content dynamically using thedrawLayer:inContext: method. Listing 2-4 shows a sample implementation of thedrawLayer:inContext: method. In this example, the delegate draws a simple curved path using a fixed width and the current rendering color.
如果没有预渲染的图片或者帮助对象来创建位图的话,你的委托可以动态地绘制图层的内容通过方法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, 5); CGContextStrokePath(theContext); // Release the path CFRelease(thePath);}仔细对比相应的方法就会知道两者的实现的用途和区别了。
For layer-backed views with custom content, you should continue to override the view’s methods to do your drawing. A layer-backed view automatically makes itself the delegate of its layer and implements the needed delegate methods, and you should not change that configuration. Instead, you should implement your view’sdrawRect: method to draw your content.
对于layer-backed视图自定义的内容,你应该重载视图的方法来完成绘制。一个layer-backed视图自动地把它本身作为它的层属性的委托并且实现了一些重要的方法,你不能修改原有的配置。而相应地,你应该重载你的drawRect:方法来绘制你的视图内容Providing Layer Content Through Subclassing
If you are implementing a custom layer class anyway, you can override the drawing methods of your layer class to do any drawing. It is uncommon for a layer object to generate custom content itself, but layers certainly can manage the display of content. For example, the CATiledLayer class manages a large image by breaking it into smaller tiles that can be managed and rendered individually.Because only the layer has information about which tiles need to be rendered at any given time, it manages the drawing behavior directly.
CATiledLayer类管理大尺寸图像通过将它分成一片的从而单独渲染(怪不得叫做tiled 砖瓦式地单独处理),因为仅仅层有关于每一处在给定的时刻需要被渲染的,它直接地对绘制行为操作。When subclassing, you can use either of the following techniques to draw your layer’s content:
- Override the layer’sdisplay method and use it to set thecontents property of the layer directly.
- Override the layer’sdrawInContext: method and use it to draw into the provided graphics context.
/* Reload the content of this layer. Calls the -drawInContext: method * then updates the `contents' property of the layer. Typically this is * not called directly. */- (void)display;
/* Called via the -display method when the `contents' property is being * updated. Default implementation does nothing. The context may be * clipped to protect valid layer content. Subclasses that wish to find * the actual region to draw can call CGContextGetClipBoundingBox(). */- (void)drawInContext:(CGContextRef)ctx;
Which method you override depends on how much control you need over the drawing process. Thedisplay method is the main entry point for updating the layer’s contents, so overriding that method puts you in complete control of the process. Overriding thedisplay method also means that you are responsible for creating theCGImageRef to be assigned to thecontents property. If you just want to draw content (or have your layer manage the drawing operation), you can override thedrawInContext:method instead and let the layer create the backing store for you.
大概解释的就是display方法是更新图层内容的主要入口,重载display方法也意味着你要为创建一个CGImageRef来赋值给contents属性。如果仅仅是为了绘制内容(或者是拥有图层管理绘制操作的使用权),你可以重载drawInContext这个方法,让图层创建backing store。Tweaking the Content You Provide
When you assign an image to thecontentsproperty of a layer, the layer’scontentsGravity property determines how that image is manipulated to fit the current bounds. By default, if an image is bigger or smaller than the current bounds, the layer object scales the image to fit within the available space. If the aspect ratio of the layer’s bounds is different than the aspect ratio of the image, this can cause the image to be distorted. You can use thecontentsGravity property to ensure that your content is presented in the best way possible.
当你分配一个图像(通常就是CGImageRef类型)给图层的contents属性时,图层的contentsGravity属性会决定了这个图像如何来适配当前的bounds(说到这里就不得不想起一篇非常的博客:关于bounds,anchorpoint,position,transform 之间很好的总结:http://blog.sina.com.cn/s/blog_8f5097be0101b91z.html),默认的,如果图像的大小比当前的bounds大或者小,图层对象将会将该图像调整成一个适当的可利用大小的空间(因为contentsGravity默认地使用:kCAGravityResize)。如果图层的宽高比与图像的宽高比不相同,这将会使得图像被扭曲。你可以使用contentsGravity属性来保证你的图像处于最好的状态。The values you can assign to thecontentsGravity property are divided into two categories:
有两种类型的属性值:- Theposition-based gravity constantsallow you to pin your image to a particular edge or corner of the layer’s bounds rectangle without scaling the image.
- The scaling-based gravity constants allow you to stretch the image using one of several options, some of which preserve the aspect ratio and some of which do not.
/** Layer `contentsGravity' values. **/CA_EXTERN NSString * const kCAGravityCenter __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityTop __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityBottom __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityLeft __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityRight __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityTopLeft __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityTopRight __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityBottomLeft __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityBottomRight __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityResize __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityResizeAspect __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);CA_EXTERN NSString * const kCAGravityResizeAspectFill __OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);关于contentsGravity的常亮属性值如上:
- Core Animation - 6
- core animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core Animation
- Core animation
- Core Animation
- Core Animation
- Android中Context详解 ---- 你所不知道的Context
- SDK Manager更新慢解决办法
- Windows下pip的安装
- lua安装流程完整流程
- magic_quotes_gpc
- Core Animation - 6
- centos彻底删除mysql
- 智能提示(二)solr词频统计(TermsComponent)
- MyEclipse10在线安装Freemarker IDE插件问题的解决办法
- 一次AIX系统报错的问题处理思路
- Phone List
- 笔记119--摘自爱哥06
- vsam
- Python 之 获取聚类中心与其支撑点的方法