容易忽略的那些小点总结 (八) —— CALayer相关(七)

版本记录

版本号 时间
V1.0 2018.01.23

前言

在苹果的API文档中,有很多属性和方法我们用的不是很多,所以很容易忽略和出错,下面我就用这一个专题专门说一些不常用的API接口,下面开始。感兴趣的可以参考前面几篇文章。
1. 容易忽略的那些小点总结 (一) —— UIView UIViewTintAdjustmentMode相关(一)
2. 容易忽略的那些小点总结 (二) —— CALayer相关(一)
3. 容易忽略的那些小点总结 (三) —— CALayer相关(二)
4. 容易忽略的那些小点总结 (四) —— CALayer相关(三)
5. 容易忽略的那些小点总结 (五) —— CALayer相关(四)
6. 容易忽略的那些小点总结 (六) —— CALayer相关(五)
7. 容易忽略的那些小点总结 (七) —— CALayer相关(六)

shadowPath

图层阴影的形状,可动画。

/* When non-null this path defines the outline used to construct the
 * layer's shadow instead of using the layer's composited alpha
 * channel. The path is rendered using the non-zero winding rule.
 * Specifying the path explicitly using this property will usually
 * improve rendering performance, as will sharing the same path
 * reference across multiple layers. Upon assignment the path is copied.
 * Defaults to null. Animatable. */

非空时,此路径定义用于构建图层阴影的轮廓,而不是使用图层的合成Alpha通道。 路径使用非零缠绕规则进行渲染。使用此属性明确指定路径通常会提高渲染性能,因为在多个图层之间共享相同的路径引用。 分配后,路径被复制。 缺省为null,可动画。

@property(nullable) CGPathRef shadowPath;

还有几点需要注意:

  • 此属性的默认值为nil,这会导致图层使用标准的阴影形状。如果为此属性指定值,则图层将使用指定的路径而不是图层的合成Alpha通道来创建其阴影。您提供的路径定义了阴影的轮廓。它使用非零缠绕规则和当前的阴影颜色,不透明度和模糊半径进行填充。

  • 与大多数动画属性不同,此属性(与所有CGPathRef动画属性一样)不支持隐式动画。但是,路径对象可以使用CAPropertyAnimation的任何具体子类来动画。路径将作为on-line点的线性混合进行插值; off-line点可以非线性插值(以保持曲线导数的连续性)。如果两个路径的控制点或段数不同,则结果是不确定的。如果路径延伸到图层边界之外,则只有在正常的图层遮罩规则导致该图层时,才会自动被图层剪切。

  • 指定显式路径通常会提高渲染性能。

  • 使用Core Foundation retain/release语义来保留此属性的值。即使属性声明似乎使用对象保留的默认分配语义事实发生此行为。

  • 您可以使用图层的阴影路径来创建特殊效果,例如模拟Pages中可用的阴影。Listing 1显示了将椭圆阴影添加到图层底部以模拟Pages Contact Shadow效果所需的代码。

// Listing 1 Creating a contact shadow path

let layer = CALayer()
     
layer.frame = CGRect(x: 75, y: 75, width: 150, height: 150)
layer.backgroundColor = NSColor.darkGray.cgColor
layer.shadowColor = NSColor.gray.cgColor
layer.shadowRadius = 5
layer.shadowOpacity = 1
     
let contactShadowSize: CGFloat = 20
let shadowPath = CGPath(ellipseIn: CGRect(x: -contactShadowSize,
                                          y: -contactShadowSize * 0.5,
                                          width: layer.bounds.width + contactShadowSize * 2,
                                          height: contactShadowSize),
                        transform: nil)
     
layer.shadowPath = shadowPath
Figure 1 Layer with contact shadow effect
  • Listing 2显示了如何创建一个模拟Pages Curved Shadow的路径。 路径的左侧,上侧和右侧是直线,底部是凹曲线,如图2所示。
Figure 2 Shadow path for curved shadow effect
// Listing 2  Creating a curved shadow path

let layer = CALayer()
layer.frame = CGRect(x: 75, y: 75, width: 150, height: 150)
layer.backgroundColor = NSColor.darkGray.cgColor
     
layer.shadowColor = NSColor.black.cgColor
layer.shadowRadius = 5
layer.shadowOpacity = 1
     
let shadowHeight: CGFloat = 10
let shadowPath = CGMutablePath()
shadowPath.move(to: CGPoint(x: layer.shadowRadius,
                            y: -shadowHeight))
shadowPath.addLine(to: CGPoint(x: layer.shadowRadius,
                               y: shadowHeight))
shadowPath.addLine(to: CGPoint(x: layer.bounds.width - layer.shadowRadius,
                               y: shadowHeight))
shadowPath.addLine(to: CGPoint(x: layer.bounds.width - layer.shadowRadius,
                               y: -shadowHeight))
     
shadowPath.addQuadCurve(to: CGPoint(x: layer.shadowRadius,
                                    y: -shadowHeight),
                        control: CGPoint(x: layer.bounds.width / 2,
                                         y: shadowHeight))
     
layer.shadowPath = shadowPath
Figure 3 Layer with curved shadow effect

preferredFrameSize

返回在其父层坐标空间中图层的首选大小

/** Layout methods. **/

/* Returns the preferred frame size of the layer in the coordinate
 * space of the superlayer. The default implementation calls the layout
 * manager if one exists and it implements the -preferredSizeOfLayer:
 * method, otherwise returns the size of the bounds rect mapped into
 * the superlayer. */

返回父层坐标空间中图层的首选frame大小。 默认实现调用布局管理器layout manager
(如果存在的话),它实现-preferredSizeOfLayer:方法,否则返回映射到父层的边界矩形的大小。

- (CGSize)preferredFrameSize;

下面我们看一下和View绑定的layer的preferredFrameSize,使用的是8plus的模拟器,代码如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSLog(@"preferredFrameSize = %@", NSStringFromCGSize(self.view.layer.preferredFrameSize));
}

下面看输出结果

2018-01-23 12:22:02.879272+0800 JJLayer_demo3[49845:33682697] preferredFrameSize = {414, 736}

+ (nullable id<CAAction>)defaultActionForKey:(NSString *)event;

返回当前类默认的action。返回给定key对应的合适的action或者当与key关联的action对象不存在时返回nil。

/** Action methods. **/

/* An "action" is an object that responds to an "event" via the
 * CAAction protocol (see below). Events are named using standard
 * dot-separated key paths. Each layer defines a mapping from event key
 * paths to action objects. Events are posted by looking up the action
 * object associated with the key path and sending it the method
 * defined by the CAAction protocol.
 *
 * When an action object is invoked it receives three parameters: the
 * key path naming the event, the object on which the event happened
 * (i.e. the layer), and optionally a dictionary of named arguments
 * specific to each event.
 *
 * To provide implicit animations for layer properties, an event with
 * the same name as each property is posted whenever the value of the
 * property is modified. A suitable CAAnimation object is associated by
 * default with each implicit event (CAAnimation implements the action
 * protocol).
 *
 * The layer class also defines the following events that are not
 * linked directly to properties:
 *
 * onOrderIn
 *      Invoked when the layer is made visible, i.e. either its
 *      superlayer becomes visible, or it's added as a sublayer of a
 *      visible layer
 *
 * onOrderOut
 *      Invoked when the layer becomes non-visible. */

/* Returns the default action object associated with the event named by
 * the string 'event'. The default implementation returns a suitable
 * animation object for events posted by animatable properties, nil
 * otherwise. */

“action”是通过CAAction协议响应“event”的对象。 Events使用标准的点分离键路径命名。 
每个图层都定义了从事件键路径到动作对象的映射。 通过查找与关键路径关联的操作对象来发布事件,
并把由CAAction协议定义的方法发送给它。

当一个action对象被调用时,它接收三个参数:命名事件的关键路径,事件发生位置的对象(即图层),
以及可选的特定于每个事件的命名参数的字典。

要为图层属性提供隐式动画,只要修改了属性的值,就会发布与每个属性同名的事件。 一个合适
的CAAnimation对象默认与每个隐式事件关联(CAAnimation实现action协议)。

图层类还定义以下不直接链接到属性的事件:

onOrderIn:在图层可见时调用,即其父图层变为可见,或者将其添加为可见图层的子图层。

onOrderOut:当图层变为不可见时调用。

返回与由字符串“event”命名的事件关联的默认action对象。 默认实现返回适合动画属性发布的
事件的动画对象,否则为nil。

+ (nullable id<CAAction>)defaultActionForKey:(NSString *)event;

还要注意以下几点:

  • 想要提供默认的actions的类可以重写这个方法并返回这些actions。

  • 我们知道Core Animation通常对CALayer的所有属性(可动画的属性)做动画,但是UIView把它关联的图层的这个特性关闭了。为了更好说明这一点,我们需要知道隐式动画是如何实现的。我们把改变属性时CALayer自动应用的动画称作行为,当CALayer的属性被修改时候,它会调-actionForKey:方法,传递属性的名称。图层首先检测它是否有委托,并且是否实现CALayerDelegate协议指定的-actionForLayer:forKey方法。如果有,直接调用并返回结果。如果没有委托,或者委托没有实现-actionForLayer:forKey方法,图层接着检查包含属性名称对应行为映射的actions字典。如果actions字典没有包含对应的属性,那么图层接着在它的style字典接着搜索属性名。最后,如果在style里面也找不到对应的行为,那么图层将会直接调用定义了每个属性的标准行为的-defaultActionForKey:方法。所以一轮完整的搜索结束之后,-actionForKey:要么返回空(这种情况下将不会有动画发生),要么是CAAction协议对应的对象,最后CALayer拿这个结果去对先前和当前的值做动画。

参考文章

1. iOS之让你的App动起来

后记

本篇已结束,后面更精彩~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容