在 极客学院 简单学习了一下 如何使用maskView设计动画效果
主要是通过CAGradientLayer 或者 带有alpha的图片来操作
//MARK:1. maskView(maskLayer)基本原理
CGFloat width = 120.f;
//底图
self.baseImageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 20, width, width)];
[_baseImageView setImage:[UIImage imageNamed:@"base"]];
[self.view addSubview:_baseImageView];
//mask 是有透明的
self.maskImageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 20 + width + 20, width, width)];
[_maskImageView setImage:[UIImage imageNamed:@"mask"]];
[self.view addSubview:_maskImageView];
//使用maskView的情况
self.addImageView = [[UIImageView alloc]initWithFrame:CGRectMake(20, 20 + (width + 20) * 2, width, width)];
[_addImageView setImage:[UIImage imageNamed:@"base"]];
UIImageView *mask = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, width, width)];
[mask setImage:[UIImage imageNamed:@"mask"]];
[_addImageView setMaskView:mask];//iOS8.0之后才有 maskView不能用addSubView的方式来添加遮罩!!!
/*iOS 8之前
// CALayer *layer = [CALayer layer];
// [layer setFrame:CGRectMake(0, 0, width, width)];
// [layer setContents:(id)[UIImage imageNamed:@"mask"].CGImage];
// [_addImageView.layer setMask:layer];
*/
[self.view addSubview:_addImageView];
//MARK:2. maskView配合CAGradientLayer的使用
// 第一步 加载图片
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(width + 40, 20, 200, 200)];
[imageView setImage:[UIImage imageNamed:@"base"]];
[self.view addSubview:imageView];
// 第二步 创建出CAGradientLayer
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[gradientLayer setFrame:imageView.bounds];//遮罩层的区域
[gradientLayer setColors:@[(__bridge id)[UIColor clearColor].CGColor,
(__bridge id)[UIColor blackColor].CGColor,
(__bridge id)[UIColor clearColor].CGColor]];//渐变的颜色数组 __bridge id类型
[gradientLayer setLocations:@[@(0.25),@(0.5),@(0.75)]];//渐变的区域 整个是1 0.25就是1/4处以此类推
[gradientLayer setStartPoint:CGPointMake(0, 0)];
[gradientLayer setEndPoint:CGPointMake(1, 0)];//渐变的方向(1,0)就是横向 (1,1)就是从左上角到右下角以此类推
// 第三步 创建一个容器View 用于加载创建出的CAGradientLayer
UIView *containerView = [[UIView alloc]initWithFrame:imageView.bounds];
[containerView.layer addSublayer:gradientLayer];
// 最后 设定maskView
imageView.maskView = containerView;
// 扩展 给maskView做动画 除了修改容器view的fram值之外 还可以动态的修改location startPoint endPoint等 实现很绚丽的动画效果
CGRect frame = containerView.frame;
frame.origin.x -= 200;//这里200是图片的宽 也就是让容器View的最右边和底层图片的最左边重合
containerView.frame = frame;
[UIView animateWithDuration:4.0f animations:^{
CGRect frame = containerView.frame;//改变位移
frame.origin.x += 400;//从左移动到右边
containerView.frame = frame;//重新赋值
}];
//MARK:3. maskView配合alpha通道图片的使用
// 添加背景图
UIImageView *backgroundView = [[UIImageView alloc]initWithFrame:CGRectMake(width + 40, 200 + 40, 200, 200)];
[backgroundView setImage:[UIImage imageNamed:@"background"]];
[self.view addSubview:backgroundView];
// 待切换图
UIImageView *baseView = [[UIImageView alloc]initWithFrame:backgroundView.frame];
[baseView setImage:[UIImage imageNamed:@"base"]];
[self.view addSubview:baseView];
// 创建maskView作为容器
UIView *maskView = [[UIView alloc]initWithFrame:baseView.bounds];
baseView.maskView = maskView;
//maskView的subView1
UIImageView *picOne = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 400)];//100背景宽一半,400背景高两倍 1的上半部是alpha为0
[picOne setImage:[UIImage imageNamed:@"1"]];
[maskView addSubview:picOne];
//maskView的subView2
UIImageView *picTwo = [[UIImageView alloc]initWithFrame:CGRectMake(100, -200, 100, 400)];//2的下半部alpha为0
[picTwo setImage:[UIImage imageNamed:@"2"]];
[maskView addSubview:picTwo];
//做切换图片的动画
[UIView animateWithDuration:2.0f animations:^{
CGRect oneFrame = picOne.frame;
oneFrame.origin.y -= 400;
picOne.frame = oneFrame;
CGRect twoFrame = picTwo.frame;
twoFrame.origin.y += 400;
picTwo.frame = twoFrame;
}];
//MARK:4. 设计文本横向渐变消失的控件
[self.view setBackgroundColor:[UIColor grayColor]];
// 创建FadeString
FadeString *fadeString = [[FadeString alloc]initWithFrame:CGRectMake(0, 400+40, 300, 40)];
[fadeString setCenter:CGPointMake(self.view.center.x, fadeString.center.y)];
fadeString.text = @"这个效果看起来还是不错的";
[self.view addSubview:fadeString];
// 执行动画效果
[fadeString fadeRight];
自定义的 FadeString.h
// 输入的文本
@property (nonatomic, strong) NSString *text;
// 向右渐变消失的方法
- (void)fadeRight;
FadeString.m
#import "FadeString.h"
@interface FadeString ()
@property (nonatomic, strong) UILabel *label; // 显示文字的label
@property (nonatomic, strong) UIView *mask; // 作为遮罩的mask
@end
@implementation FadeString
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// 创建出label
[self createLabel:self.bounds];
// 创建出mask
[self createMask:self.bounds];
}
return self;
}
- (void)createLabel:(CGRect)frame {
self.label = [[UILabel alloc]initWithFrame:frame];
[_label setFont:[UIFont systemFontOfSize:25.0f]];
[_label setTextAlignment:NSTextAlignmentCenter];
[_label setTextColor:[UIColor whiteColor]];
[self addSubview:_label];
}
- (void)createMask:(CGRect)frame {
//创建出渐变的layer
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
[gradientLayer setFrame:frame];
[gradientLayer setColors:@[(__bridge id)[UIColor clearColor].CGColor,
(__bridge id)[UIColor blackColor].CGColor,
(__bridge id)[UIColor blackColor].CGColor,
(__bridge id)[UIColor clearColor].CGColor]];
[gradientLayer setLocations:@[@(0.01), @(0.1), @(0.9), @(0.99)]];
[gradientLayer setStartPoint:CGPointMake(0, 0)];
[gradientLayer setEndPoint:CGPointMake(1, 0)];
// 创建并接管mask
self.mask = [[UIView alloc]initWithFrame:frame];
// mask获取渐变layer
[self.mask.layer addSublayer:gradientLayer];
self.maskView = _mask;
}
- (void)fadeRight {
//当前的设计是有缺陷的 最好加上两个参数 一个动画时间 一个是否执行动画
[UIView animateWithDuration:3.f animations:^{
CGRect maskFrame = _mask.frame;
maskFrame.origin.x += _mask.frame.size.width;
_mask.frame = maskFrame;
}];
}
//MARK:重写set,get方法
@synthesize text = _text;
- (void)setText:(NSString *)text {
_text = text;
self.label.text = text;
}
- (NSString *)text {
return _text;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
极客学院的视频地址:http://www.jikexueyuan.com/course/1257.html
其中:
__bridge只做类型转换,但是不修改对象(内存)管理权;
__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;
__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。
关于这方面的解释 https:developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;
__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。
关于这方面的解释 https:developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html