CAPLayer Tutorial: Getting Started[翻译]

最近做一个图的加载动态效果时,看到一篇教程,不过他是在CAShapeLayer上完成的,当时我对CALayer并不是很了解。raywenderlich上的这篇文章有对它的具体介绍。采用的是swift,我把他改为了Objective-C,顺带翻译了带有简单例子的一段。

Brief Introduction

你可能会知道,在iOS app中你看到的所有东西都是view,含有button views,table views,slider views,甚至还有包含其他views的parent views。
但是你可能不知道每一个view后都有一个layer,比较特殊的是CAPlayer。
在这篇文章,你将会学习到什么是CAPlayer和它如何使用。此时,将假定你对于iOS app开发和Objective-C的基础很熟悉,包括在storyboard中构造你的UI。

Getting Started

想知道layers到底是什么最好的方法就是亲自动手做一个。所以让我们开始创建一个简单的工程
准备好去写一些代码了吗?好,打开Xcode然后:

  1. 点击menu选择File\New\Project..
  2. 从dialog选择iOS\Application\Single View Application
  3. 点击Next,在Product Name后输入CALayerPlayground,以及填写其他项目
  4. 选择Objective-C作为语言和Universal for Devices
  5. 注意不要选择Core Data
  6. 找到一个地方存在你的project,然后点击Create
  7. 在左侧Project navigator 选择Main.storyboard
  8. 点击menu选择View\Assistant Editor\Show Assistant Editor,如果Object Library没有显示的话,点击View\Utilities\Show Object Library使其显示
  9. 同时,选择Editor\Canvas\Show Bounds Rectangles,这样当你想添加一个view,就可以看到每一个view的边界轮廓
  10. 从Object library中拉出一个view倒View Controller Scene中。选中他,去右方的Sizeinspector((View\Utilities\Show Size Inspector),将x、y设为150,width、height设为300
  11. 在auto layout toolbar中点击Align按钮(storyboard的右下角)然后点击Horizontal Center in Container和Vertical Center in Container,将他们的Values设为0。最后点击Add 2 Constraints
  12. 点击Pin按钮,检查Width和Height,确定他们的值都设为300,and点击Add 2 Contstraints
    最后,按住ctrol并拖住view到文件ViewController.m的@interface与@end中间。在出现的弹出窗口中,将这个outlet命名为viewForLayer。你的Xcode现在需要看起来像这个

image

点击Connect去创建outlet
将ViewController.m替换内容如下:

 #import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *viewForLayer;

@end

@implementation ViewController

//CALayer *l = lorLayer.layer;
- (void)viewDidLoad {
    [super viewDidLoad];
    [self setUpPlayer];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)setUpPlayer{
    CALayer *l = _viewForLayer.layer;
    l.backgroundColor = [[UIColor blueColor] CGColor];
    l.borderWidth = 100.0;
    l.borderColor = [[UIColor redColor]CGColor];
    l.shadowOpacity = 0.7;
    l.shadowRadius = 10.0;//default :3
    l.contents = (__bridge id _Nullable)([[UIImage imageNamed:@"star"] CGImage]);
    l.contentsGravity = kCAGravityCenter;
    
}

正如前文所提到的,每一个ios中的view都有一个layer与其联系,你可以使用yourView.layer调用layer。故我们要做的第一件事是创建一个preoperty l(L的小写)去调用viewForlayer的layer,这样做可以减少你敲击键盘的次数。
这段代码同样调用了setUpLayer去设置一些关于layer的属性:shadow,background,border.你将会对setUppLayer了解更多的,不过首先我们要先用iOS Simulator(iOS模拟器)运行一下程序,检查一下你的自定义layer:


几行代码就有十分cool的效果是吧?还有再来一次=因为每一个view背后都有一个layer,你可以在你的app中对于任何view做这种事情。接下来,让我们更进一步吧!

Basic CALayer Properties

CaLayer有一些属性可以让你自定义他的外形。回头思考一下你已经做了什么:

  • 改变了layer的背景颜色,(none->blue)
  • 改变了borer的大小 (0->100)
  • 改变了她本身的颜色 (black->red)
  • 最后,你加上了一个shadow。通过改变shadow opacity(0->0.7)来实现的;改变opacity只会让shadow显现,然后你更进一步改变了shadow radius(3->10),其中3为默认半径。

你仍旧可以设置一些属性在CALayer。让我们再来一次。在setUpLayer()中增加:

 l.contents = (__bridge id _Nullable)([[UIImage imageNamed:@"star"] CGImage]);    
 l.contentsGravity = kCAGravityCenter;```
 
 在CALayer中content的属性允许你修改layer的内容变为图片,所以你可以设置图star。可以[在这里下载](http://cdn4.raywenderlich.com/wp-content/uploads/2014/12/star.png),然后添加到你的项目中。  
 创建运行,然后花一点时间去欣赏这个极好的艺术品:  
 ![](http://upload-images.jianshu.io/upload_images/669709-d64b91e64216712b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  
 注意下star是怎样在中间的-这是因为你设置了contentGravity为KCAGravityCenter。正如你可能期望的,你还可以改变gravity为top,right,bottom-right,bottom,bottom-left和top-left。  
 ##Changing the Layer's Appearance  
 就当是为了好玩,让我们增加一些手势去操作layer的外表。从Object Library拖出一个tap gesture recognizer,覆盖在viewForLayer上。就像:
![](http://upload-images.jianshu.io/upload_images/669709-8fbc8ef687a333f3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  
 重复这个操作去添加pinch gesture recognizer在viewForLayer。  
 然后control-drag两个gesture recognizer到ViewControll.m,位置在setUpLayer()与类的最后的大括号中间。例如:
 ![](http://upload-images.jianshu.io/upload_images/669709-aaf6945e3e8bde2b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 像这样更改tapGestureRecognized(_:):  
 
 ```Objective-C
  - (IBAction)tapGestureRecognized:(UITapGestureRecognizer *)sender {
    CALayer *l = _viewForLayer.layer;
//    l.shadowOpacity = (l.shadowOpacity == 0.7)? 0.0:0.7;
    if (l.shadowOpacity == 0.7) {
        l.shadowOpacity = 0.0;
    }else{
        l.shadowOpacity = 0.7;
    }    
}```

这告诉viewForLayer在tap时,控制layer的shadow opacity在0.7、0之间。  
你是说这个view?当然了。你可以重写CALayer的hitTest(_:)去做一样的事情。但是在这个方法里有一个逻辑,每一个layer也只能做hit testing,因为它不能对recognized gesture做出相应反应。所以你需要建立一个tap recognizer。
现在更改pinchGestureRecognized(_:)如下:

  • (IBAction)pinchGestureRecognized:(UIPinchGestureRecognizer *)sender {
    CALayer l = _viewForLayer.layer;
    CGFloat offset = (sender.scale <1) ? 0.5 :-0.5;
    const CGRect oldFrame = l.frame;
    const CGPoint oldOrigin = oldFrame.origin;
    const CGPoint newOrigin = CGPointMake(oldOrigin.x+offset, oldOrigin.y+offset);
    const CGSize newSize = CGSizeMake(oldFrame.size.width+(offset * -2.0), oldFrame.size.width+(offset
    -2.0));
    const CGRect newFrame = CGRectMake(newOrigin.x, newOrigin.y, newSize.width, newSize.height);
    if (newFrame.size.width >= 100.0 && newFrame.size.width<=300.0) {
    l.borderWidth -= offset;
    l.cornerRadius +=(offset/2.0);
    l.frame = newFrame;
    }```

这里你在创建一个基于user's pinch positive或者negative offset,然后调整layer的frame size,border width与boder的conrner radius。
layer的corner radius的默认值是0,意味着一开始是一个90°矩形。xxxxxxxxxxxxx。想要xxxxx?设置corner radius为width的一半。
注意改变corner radius并没有剪切layer content(图star),除非你将masksToBounds设置为true。
Build & Run,然后试着点和放大缩小。



嘿,多一点打磨,你成为一个很漂亮的阿凡达的制造者!

这里附上我的code.

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

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,473评论 6 30
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,417评论 2 45
  • http://mp.weixin.qq.com/s/vNtXHTBkRL569DWCg-6c2w
    凤凰涅槃_与死神交锋阅读 150评论 0 0
  • 下载了简书后,第一个想找的词汇是许嵩,第一个想看到的是关于大家对他的评论,想和大家找一个共同的话题,去谈论。不知什...
    花满楼y阅读 234评论 0 0
  • 春天的明媚,和黄色相互辉映 那是闪耀着灿烂的颜色 麦田隐匿 油菜花铺垫的田野 一望无际的壮阔 那是属于平原的春天 ...
    清明好时光阅读 348评论 1 5