ios UIView的mask属性,view和layer的关系

mask属性 : https://www.jianshu.com/p/fe4124de3729

view和layer的关系 : https://www.jianshu.com/p/9c7a23ea705b

什么是mask:

CALayer有一个属性叫做mask,通常被称为蒙版图层,mask类似于子视图,但却不是一个普通的子视图,它本身也是CALayer类型,具有和其他图层一样的绘制和布局属性。

mask 的作用就是让父图层与mask重叠的部分区域可见 , 通俗的说就是mask图层实心的部分将会被保留下来,mask与父视图不重合的部分则会被抛弃

    self.view.backgroundColor = [UIColor cyanColor];
    
    UIView * red = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 414, 600)];
    red.backgroundColor = [UIColor redColor];
    [self.view addSubview:red];

    
    // mask所在区域会显示,不在区域不显示,类似于透明度为0
//    UIBezierPath *bpath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:100 startAngle:0 endAngle:2*M_PI clockwise:NO];
    UIBezierPath *bpath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];

    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = bpath.CGPath;
    //添加图层蒙板
    red.layer.mask = shapeLayer;

1.mask 的backgroundColor必须设置,不设置mask 背景就是透明的,mask 是不会起作用的,但是backgroundColor设置什么颜色无所谓。

    CALayer * layer = [CALayer layer];
    layer.frame = CGRectMake(100, 100, 100, 100);
    // 注释了下面在设置mask就无效了
    layer.backgroundColor = [UIColor orangeColor].CGColor;
    red.layer.mask = layer;

2.为一个layer的mask 创建一个新的mask时,这个新的mask不能有superlayer 和sublayer。(官方文档的说明)

3.mask 可以配合CAGradientLayer、CAShapeLayer 使用。可以实现蒙层透明度、显示不同形状图层、图案镂空、文字变色等等功能。

4.mask在动画中使用,可以产生很好的动画效果。

说下 UIView和layer的关系
1. UIView不具备显示功能,拥有显示功能的是它内部的图层即CALayer属性

当UIView需要显示到屏幕上时,会调用DrawRect:方法进行绘图,并且将所有的内容绘制在自己的图层上CALayer *layer,绘图完成后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示

UIView 的Layer属性在系统内部,被维护着三份拷贝。分别是逻辑树(self.view.layer.modelLayer),这里是代码可以操作的;动画树,是一个中间层,系统就在这一层上更改属性,进行各种渲染操作;显示树(self.view.layer.presentationLayer),其内容就是当前正被显示在屏幕上的内容

UIView 本身更像是一个CALayer的管理器,UIView 有个属性CALayer *layer ,所有从UIView继承的对象都继承了该属性。因此,可以通过layer 属性对view 进行 转换、缩放、旋转等操作 .


2.UIView可以响应事件,Layer不可以.

UIKit使用UIResponder作为响应对象,来响应系统传递过来的事件并进行处理。UIApplication、UIViewController、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。

在 UIResponder中定义了处理各种事件和事件传递的接口, 而 CALayer直接继承 NSObject,并没有相应的处理事件的接口。
 

I、下面就展示一下mask 高级的用法:

代码如下, 下载https://github.com/guochaoshun/maskDemo

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *bgImageView;
@property (weak, nonatomic) IBOutlet UIImageView *hiddenImageView;

@property (nonatomic, strong) CALayer *maskLayer; // 方式1
@property (nonatomic, strong) UIView *maskView; // 方式2

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setUpSubView];

}

- (void)setUpSubView {

    self.hiddenImageView.userInteractionEnabled = YES;
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
    [self.hiddenImageView addGestureRecognizer:pan];


    CGFloat width = 300;
    // 方式1: 通过layer.mask
    self.maskLayer = [CALayer layer];
    self.maskLayer.frame = CGRectMake(0, 0, width, width);
    self.maskLayer.cornerRadius = width*0.5;
    self.maskLayer.backgroundColor = UIColor.whiteColor.CGColor;
    self.hiddenImageView.layer.mask = self.maskLayer;

    // 方式2: 通过view.maskView实现效果一致
//    self.maskView = [[UIView alloc] initWithFrame:CGRectMake(20, 200, width, width)];
//    self.maskView.backgroundColor = UIColor.whiteColor;
//    self.maskView.layer.cornerRadius = width*0.5;
//    self.hiddenImageView.maskView = self.maskView ;
}

- (void)panAction:(UIPanGestureRecognizer *)pan {

    switch (pan.state) {
        case UIGestureRecognizerStateBegan: {// 开始拖拽

        }
            break;
        case UIGestureRecognizerStateChanged: {// 拖拽中
            CGPoint translation = [pan translationInView:self.hiddenImageView];
            if (self.maskLayer) {
                // CATransaction有隐式动画,使用CATransaction禁调隐式动画
                // 如果没有setDisableActions,这样会导致拖动的时候不跟手
                [CATransaction begin];
                [CATransaction setDisableActions:YES];
                self.maskLayer.position = CGPointMake(self.maskLayer.position.x+translation.x, self.maskLayer.position.y+translation.y);
                [CATransaction commit];
            } else if (self.maskView) {
                self.maskView.center = CGPointMake(self.maskView.center.x+translation.x, self.maskView.center.y+translation.y);
            }
            [pan setTranslation:CGPointZero inView:self.hiddenImageView];

        }
            break;
        case UIGestureRecognizerStateEnded: {// 拖拽结束

        }
            break;
        default: {// 其他异常情况当拖拽结束处理

        }
            break;
    }

}


@end

再来一个渐隐效果,了解CAGradientLayer的作用https://blog.csdn.net/u014600626/article/details/73648093

下载地址同上: https://github.com/guochaoshun/maskDemo


- (void)viewDidLoad {
    [super viewDidLoad];

    [self setUpSubView];
}

- (void)setUpSubView {
    
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];

    [self.view layoutIfNeeded];
    // 添加渐隐层,bgView是tableView的父视图
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.colors = @[(__bridge id)[UIColor clearColor].CGColor, (__bridge id)[UIColor whiteColor].CGColor];
    gradientLayer.locations = @[@0, @1];
    gradientLayer.startPoint = CGPointMake(0, 0);
    gradientLayer.endPoint = CGPointMake(0, 0.15);
    gradientLayer.frame = CGRectMake(0, 0, self.bgView.frame.size.width, self.bgView.frame.size.height);
    self.bgView.layer.mask = gradientLayer;
}

II、下面展示的是和CAShapeLayer结合使用的情况

- (UIView*)shapeView {

    if(_shapeView==nil) {

        _shapeView = [[UIView alloc] initWithFrame:CGRectMake(50, 200, UIScreen.mainScreen.bounds.size.width - 50*2, 200)];

        _shapeView.backgroundColor = UIColor.grayColor;

        CAShapeLayer *shapeLayer = [CAShapeLayer layer];

        UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:_shapeView.bounds];

        shapeLayer.path= bezierPath.CGPath;

        shapeLayer.strokeStart=0.0;

        shapeLayer.strokeEnd=1.0;

        shapeLayer.fillColor = UIColor.orangeColor.CGColor;

        shapeLayer.lineWidth=1.5;

        [_shapeView.layer addSublayer:shapeLayer];

     //   _shapeView.layer.mask= shapeLayer;     >>>>>>>>>>>>>>>>>>>>>AAA行

    }

    return _shapeView;

}

上面这段代码就是mask 和 CAShapeLayer 结合使用的简单示例:

上面代码AAA行注释掉的情况

shapeLayer 没有赋值给mask情况

上面代码AAA没有注释掉的情况:

mask被赋值了shapeLayer的情况

通过这两张图对比可以看出mask 和shapeLayer结合使用,可以在父图层上显示你想要的图形,而父图层的其它部分,则被隐去了 。

III、扩展

使用layer的mask属性实现注水动画效果

mask和shapeLayer 结合 实现的圆形动画加载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值