码迷,mamicode.com
首页 > 其他好文 > 详细

CALayer 基础

时间:2015-02-05 15:01:39      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:

UIView在ios开发里面是非常重要的。几乎所有的控件都是从UIView继承下来的。比如UILabel,UIText等。

今天有空看了一下UIView的内部结构。发现其实UIView的显示部分其实委托给CALayer(Core Animation Layer)来做的。

UIView类片段

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace> {
  @package
    CALayer        *_layer;
    id              _gestureInfo;
    NSMutableArray *_gestureRecognizers;
    NSArray        *_subviewCache;
    float           _charge;
    NSInteger       _tag;
    UIViewController *_viewDelegate;
    NSString         *_backgroundColorSystemColorName;
    NSUInteger      _countOfMotionEffectsInSubtree;
里面有个CALayer的成员。

CALayer的主要功能就是在屏幕上显示东西了。

CALayer属性

我们可以通过CALayer的属性来改变图层的一些外观。

- (IBAction)btnClick:(id)sender {
    CALayer *sublayer =[CALayer layer];
    sublayer.backgroundColor =[UIColor blueColor].CGColor;
    sublayer.shadowOffset = CGSizeMake(0, 3);
    sublayer.shadowRadius =5.0;
    sublayer.shadowColor =[UIColor blackColor].CGColor;
    sublayer.shadowOpacity = 1;
    sublayer.frame = CGRectMake(150, 20, 128, 50);
    sublayer.borderColor =[UIColor blackColor].CGColor;
    sublayer.borderWidth =2.0;
    sublayer.cornerRadius =10.0;
    sublayer.anchorPoint = CGPointMake(0, 0);
    [self.view.layer addSublayer:sublayer];
    
    CABasicAnimation *animation = [ CABasicAnimation animationWithKeyPath: @"transform" ];
    animation.toValue = [ NSValue valueWithCATransform3D: CATransform3DMakeRotation(3.1415, 0, 0, 1.0) ];
    animation.duration = 2;
    animation.cumulative = YES;
    animation.repeatCount = 2;
    [sublayer addAnimation: animation forKey: @"animation" ];
    
}
上面的代码主要分几部分:

1. 创建一个CALayer的实例

2. 修改一些属性,比如阴影,圆角等。

3. 把新创建的CALayer实例加到当前view的层里面,作为子层。

4. 给新创建的CALayer实例增加一个动画效果。

技术分享

点一下第一个按钮,就会发现有个蓝色的图层(CALayer),会旋转一圈。这些都是刚才的那些代码做的事情,非常简单。


CALayer显示图片

在ios上显示一张图片其实很简单,搞个ImageView控件就可以了。

实际上ImageView也是从UIView继承下来的,其实也是通过CALayer显示的。那么如果使用CALayer直接显示一张图片呢?

通过下面的代码就可以搞定了:

- (IBAction)btnContent:(id)sender {
    CALayer *sublayer =[CALayer layer];
    sublayer.backgroundColor =[UIColor orangeColor].CGColor;
    sublayer.shadowOffset = CGSizeMake(0, 3);
    sublayer.shadowRadius =5.0;
    sublayer.shadowColor =[UIColor blackColor].CGColor;
    sublayer.shadowOpacity = 1;
    
    sublayer.borderColor =[UIColor blackColor].CGColor;
    sublayer.borderWidth =2.0;
    sublayer.cornerRadius =10.0;
    sublayer.anchorPoint = CGPointMake(0, 0);
    [self.view.layer addSublayer:sublayer];

    CGImageRef img = [UIImage imageNamed:@"Image"].CGImage;
    sublayer.contents = (__bridge id)img;
    sublayer.frame = CGRectMake(180, 60, CGImageGetWidth(img), CGImageGetWidth(img));
    
    CABasicAnimation *animation = [ CABasicAnimation animationWithKeyPath: @"transform" ];
    animation.toValue = [ NSValue valueWithCATransform3D: CATransform3DMakeRotation(3.1415, 0, 0, 1.0) ];
    animation.duration = 2;
    animation.cumulative = YES;
    animation.repeatCount = 2;
    [sublayer addAnimation: animation forKey: @"animation" ];
}
代码也分几个部分

1. 创建一个新的CALayer对象

2. 设置一些属性

3. 把这个新创建的对象加到当前的view的CALayer里面。

4. 获取一张图片对象,赋给CALayer的contents

5. 跟前面一样,加个动画。

运行一下:

技术分享

从截图里可以看到图片显示出来了(qq头像),并且有个旋转的动画效果。

CALayer是可以叠加的,如果有多个图片,那么就可以创建多个CALayer对象,一个个叠上去,同时还可以设置一些动画效果啥的。

比如,一个view消失的时候,我们可以放一些玻璃碎片图片上去,给每个CALayer对象加个掉下来的动画,这样看起来就像是玻璃破碎一样。


CALayer自定义绘画

除了简单修改CALayer对象属性和显示一张图片外,我们还可以自己绘制图层的内容。

先给出代码:

- (IBAction)btnCustomDraw:(id)sender {
    CALayer *customDrawn = [CALayer layer];
    customDrawn.delegate = self;
    customDrawn.backgroundColor = [UIColor greenColor].CGColor;
    customDrawn.frame = CGRectMake(180, 100, 128, 40);
    customDrawn.shadowOffset = CGSizeMake(0, 3);
    customDrawn.shadowRadius = 5.0;
    customDrawn.shadowColor = [UIColor blackColor].CGColor;
    customDrawn.shadowOpacity = 0.8;
    customDrawn.cornerRadius = 10.0;
    customDrawn.borderColor = [UIColor blackColor].CGColor;
    customDrawn.borderWidth = 2.0;
    customDrawn.masksToBounds = YES;
    [self.view.layer addSublayer:customDrawn];
    [customDrawn setNeedsDisplay];
}

void MyDrawColoredPattern (void *info, CGContextRef context) {
    
    CGColorRef dotColor = [UIColor colorWithHue:0 saturation:0 brightness:0.07 alpha:1.0].CGColor;
    CGColorRef shadowColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.1].CGColor;
    
    CGContextSetFillColorWithColor(context, dotColor);
    CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 1, shadowColor);
    
    CGContextAddArc(context, 3, 3, 4, 0, 3.14, 0);
    CGContextFillPath(context);
    
    CGContextAddArc(context, 16, 16, 4, 0, 3.14, 0);
    CGContextFillPath(context);
    
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
    
    CGColorRef bgColor = [UIColor colorWithHue:0.6 saturation:1.0 brightness:1.0 alpha:1.0].CGColor;
    CGContextSetFillColorWithColor(context, bgColor);
    CGContextFillRect(context, layer.bounds);
    
    static const CGPatternCallbacks callbacks = { 0, &MyDrawColoredPattern, NULL };
    
    CGContextSaveGState(context);
    CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
    CGContextSetFillColorSpace(context, patternSpace);
    CGColorSpaceRelease(patternSpace);
    
    CGPatternRef pattern = CGPatternCreate(NULL,
                                           layer.bounds,
                                           CGAffineTransformIdentity,
                                           24,
                                           24,
                                           kCGPatternTilingConstantSpacing,
                                           true,
                                           &callbacks);
    CGFloat alpha = 1.0;
    CGContextSetFillPattern(context, pattern, &alpha);
    CGPatternRelease(pattern);
    CGContextFillRect(context, layer.bounds);
    CGContextRestoreGState(context);
}

创建CALayer对象那部分代码和前面的很相似,唯一的区别就是设置了一个委托
customDrawn.delegate = self;
我们需要实现一个drawLayer的函数。这个函数是个非正式协议,也就是NSObject的类别,所以所有的OC对象都有这个函数的声明。看下面的代码,可以清楚的看到这函数。

@interface NSObject (CALayerDelegate)

/* If defined, called by the default implementation of the -display
 * method, in which case it should implement the entire display
 * process (typically by setting the `contents' property). */

- (void)displayLayer:(CALayer *)layer;

/* If defined, called by the default implementation of -drawInContext: */

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;

/* Called by the default -layoutSublayers implementation before the layout
 * manager is checked. Note that if the delegate method is invoked, the
 * layout manager will be ignored. */

- (void)layoutSublayersOfLayer:(CALayer *)layer;

/* If defined, called by the default implementation of the
 * -actionForKey: method. Should return an object implementating the
 * CAAction protocol. May return 'nil' if the delegate doesn't specify
 * a behavior for the current event. Returning the null object (i.e.
 * '[NSNull null]') explicitly forces no further search. (I.e. the
 * +defaultActionForKey: method will not be called.) */

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event;

@end

我们实现了drawLayer这个函数后,那么就可以在里面自己来画东西了。通常都是使用core graphics来画的。

运行结果:

技术分享


基本上有关CALayer的绘制就这么几种吧

1. 最简单的设置属性

2. 显示图片

3. 自定义绘制。

有了这些基础后,配合动画就可以做一些比较炫的ui界面了。

动画和core graphics后面有机会再研究。









CALayer 基础

标签:

原文地址:http://blog.csdn.net/zj510/article/details/43526995

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!