什么是图层
在iOS开发当中,我们所接触到的所有视图都继承来自UIView类,UIView的各种子类构成了我们在ios设备上所交互的界面。UIView能够展示界面交互的元素,识别出用户的触摸事件,是搭建iOS应用的基础元素。在底层实现当中,UIView将视图的绘制工作与触摸事件的响应进行了分离。UIView并不直接完成视图的绘制工作,它将视图的绘制交给了图层,也就是本文的介绍对象——图层来完成。在iOS当中,所有的图层来继承于CALayer类。
为什么要直接使用图层
既然图层是UIView底层实现所使用到的,UIView在封闭时也暴露了视图控制的诸多接口,那为什么我们还要直接使用图层呢?这是由于虽然UIView对图层做了封装,但图层的诸多接口并没有对外暴露出来,其中包括下面的特性,这些特性在应用开发当中有可能会遇到。
- 阴影,圆角,带颜色的边框
- 3D变换
- 非矩形范围
- 透明遮罩
- 多级非线性动画
图层的特性
-
阴影及圆角
在iOS应用当中 ,圆角的使用场景非常广泛。圆角的图片、图标在UI设计当中经常被使用,阴影能够让视图产生立体感,拟物感强。通过操作CALayer对象的cornerXXX属性及shadowXXX属性,可以让视图产生阴影效果及圆角修饰。下图展示了阴影及圆角的一个示例demo图。
- (void)setShadowView
{
UIView *shadowView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
shadowView.center = self.view.center;
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowOffset = CGSizeMake(0, -3);
shadowView.layer.shadowOpacity = 0.5;
UIView *view1 = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
view1.backgroundColor = [UIColor grayColor];
view1.layer.cornerRadius = 10.0;
// view1.layer.masksToBounds = YES;
[shadowView addSubview:view1];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
view2.center = CGPointMake(0, 0);
view2.layer.cornerRadius = 10.0;
view2.backgroundColor = [UIColor redColor];
[view1 addSubview:view2];
[self.view addSubview:shadowView];
}
-
图层蒙版
我们平常接触的视图都是由矩形构成的,但很多情况下,我们希望图层能够以自定义的形状进行显示,例如我只希望图标部分显示出来,其它地方是透明。CALayer本身提供了遮罩层的属性即mask属性,通过该属性,我们可以实现photoshop当中图层蒙版的效果。下图当中使用了一张图片(即左图)来当作蒙版,只有图片有内容的部分才能显示出来,其它地方都透明的。该蒙版被应用到右边的视图当中,最终右边视图显示出的背景颜色与左图轮廓一致。
- (void)setMaskView
{
UIImage *image = [UIImage imageNamed:@"default"];
UIView *imageView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.layer.contents = (__bridge id)image.CGImage;
imageView.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2 - 70, [UIScreen mainScreen].bounds.size.height / 2);
[self.view addSubview:imageView];
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
view1.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2 + 70, [UIScreen mainScreen].bounds.size.height / 2);
view1.backgroundColor = [UIColor yellowColor];
[self.view addSubview:view1];
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = view1.bounds;
maskLayer.contents = (__bridge id)image.CGImage;
view1.layer.mask = maskLayer;
}
-
3D变换
UIView的变换属性只提供了在二维坐标的变换,而�图层则提供了进行3D变换的属性,即transform属性。通过3D变换的操作,我们可以实现自定义变换效果,特别是在自定义复杂的动画效果上非常有用。下面是通过3D变换构建的一个立方体。
- (void)setCreateCube
{
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
containerView.center = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, [UIScreen mainScreen].bounds.size.height / 2);
[self.view addSubview:containerView];
NSMutableArray *labelArray = [NSMutableArray new];
for (NSInteger i = 0; i < 6; i ++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
label.text = [NSString stringWithFormat:@"%ld",(long)i];
label.textColor = [UIColor blackColor];
label.textAlignment = NSTextAlignmentCenter;
int redRand = arc4random_uniform(255);
int greenRand = arc4random_uniform(255);
int blueRand = arc4random_uniform(255);
label.backgroundColor = [UIColor colorWithRed:redRand/255.0
green:greenRand/255.0
blue:blueRand/255.0
alpha:1.0];
label.layer.borderColor = [UIColor grayColor].CGColor;
label.layer.borderWidth = 1.0;
[labelArray addObject:label];
[containerView addSubview:label];
}
UIView *view1 = labelArray[0];
UIView *view2 = labelArray[1];
UIView *view3 = labelArray[2];
UIView *view4 = labelArray[3];
UIView *view5 = labelArray[4];
UIView *view6 = labelArray[5];
CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/500;
perspective = CATransform3DRotate(perspective, -M_PI_4, 1, 0, 0);
perspective = CATransform3DRotate(perspective, -M_PI_4, 0, 1, 0);
containerView.layer.sublayerTransform = perspective;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 0, 0, 100);
view1.layer.transform = transform;
transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 100, 0, 0);
transform = CATransform3DRotate(transform, M_PI / 2, 0, 1, 0);
view2.layer.transform = transform;
transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, -100, 0, 0);
transform = CATransform3DRotate(transform, -M_PI / 2, 0, 1, 0);
view3.layer.transform = transform;
transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 0, 0, -100);
transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);
view4.layer.transform = transform;
transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 0, -100, 0);
transform = CATransform3DRotate(transform, M_PI / 2, 1, 0, 0);
view5.layer.transform = transform;
transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, 0, 100, 0);
transform = CATransform3DRotate(transform, -M_PI / 2, 1, 0, 0);
view6.layer.transform = transform;
}