零基础iOS开发学习日记—控件篇—CALayer、动画、手势

开头

CALayer

实际用处

  • 更直接得设置控件的样式
  • 控件动画

基础用法

  • 设置样式,大多情况是设置圆角
UIView *redView = [UIView new];
redView.frame = CGRectMake(100, 100, 100, 100);
redView.backgroundColor = [UIColor redColor];
//设置边框
redView.layer.borderWidth = 10;
//边框颜色
redView.layer.borderColor = [UIColor grayColor].CGColor;
//阴影
redView.layer.shadowOffset = CGSizeMake(4, 4); //偏移,以左上角为原点
redView.layer.shadowColor = [UIColor blueColor].CGColor;
redView.layer.shadowRadius = 10; // 阴影半径
redView.layer.shadowOpacity = 1; //设置透明度
//圆角
redView.layer.cornerRadius = 20;
//超出layer的范围不显示,超出范围的阴影也会被裁掉
redView.layer.masksToBounds = YES; 
//bounds 大小
redView.layer.bounds = CGRectMake(0, 0, 200, 200);
//position 默认指的是center
redView.layer.position = CGPointMake(0, 0);
//设置内容 __bridge id
redView.layer.contents = (__bridge id)([UIImage imageNamed:@"Gin_1"].CGImage);
[self.view addSubview:redView];
复制代码
  • 设置动画
//旋转
//旋转到某个角度 角度,x,y,z
self.layer.transform = CATransform3DMakeRotation(M_PI_4, 1, 0, 0);
//旋转了某个角度 初始的frame,角度,x,y,z
self.layer.transform = CATransform3DRotate(self.layer.transform, M_PI_4, 0, 0, 1);
//缩放 初始的frame,x的缩放比例,y的缩放比例,z的缩放比例
self.layer.transform = CATransform3DScale(self.layer.transform, 0.5, 0.5, 0.1);
//平移 初始的frame,x的移动,y的移动,z的移动
self.layer.transform = CATransform3DTranslate(self.layer.transform, 10, 0, 10);
复制代码

隐式动画

  • 自定义layer
CALayer *layer = [CALayer new];
layer.backgroundColor = [UIColor redColor].CGColor;
layer.position = CGPointMake(200, 200);
layer.bounds = CGRectMake(0, 0, 100, 100);
layer.contents = (__bridge id)[UIImage imageNamed:@"Gin_1"].CGImage;
//添加
[self.view.layer addSublayer:layer];
复制代码
  • CALayer自带隐式动画,也就是说,当改变控件layer时,会有一定的变化动,自动产生动画效果
  • 而根控件layer指的是,直接从创建的控件获取的layer是没有隐式动画的
//获取触摸对象
UITouch *t = touches.anyObject;
CGPoint p = [t locationInView:t.view];
//自带隐式动画 根控件没有隐式动画
self.layer.bounds = CGRectMake(0, 0, 200, 200);
self.layer.opacity = 0.5;
self.layer.position = p;
复制代码
  • 禁用隐式动画
//获取触摸对象
UITouch *t = touches.anyObject;
CGPoint p = [t locationInView:t.view];
//自带隐式动画 根控件没有隐式动画
self.layer.bounds = CGRectMake(0, 0, 200, 200);
self.layer.opacity = 0.5;
//禁用隐式动画
[CATransaction begin]; // 开启事物
[CATransaction setDisableActions:YES]; // 禁用隐式动画
self.layer.position = p;
[CATransaction commit]; // 提交
复制代码

核心动画

实际用处

  • 使控件运动

基础用法

基本动画

  • 直接对layer属性进行操作
//1.创建动画
CABasicAnimation* anim = [CABasicAnimation new];
//2.做什么动画
anim.keyPath = @"position.x";
//    anim.fromValue = @(10);
//    anim.toValue = @(300);
//累加
//    anim.byValue = @(10);
//开始时间
anim.beginTime = CACurrentMediaTime() + 3;
//起始值
anim.fromValue = @300;
//结束值
anim.toValue = @400;
anim.duration = 3;
/**
 kCAFillModeForwards //动画开始3秒后,从初始位置跳到x=300,移动到400
 kCAFillModeBackwards //动画开始后,直接跳到动画开始的位置,如上面跳到x=300处,3秒后到500,并结束后回到最初的位置
 kCAFillModeBoth //包括上面两个
 kCAFillModeRemoved 默认回到初始位置
 */
//默认会回到原来位置,不回到原来的位置
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;
//3.添加动画(谁做动画)
[self.layer addAnimation:anim forKey:nil];
复制代码

关键帧动画

  • layer在运动到打下的一个个帧点
//关键帧动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation new];
anim.keyPath = @"position";
NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(150, 100)];
NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 150)];
NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(150, 150)];
//关键帧数据
anim.values = @[v1,v2,v3,v4];
//路径动画
//    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2 * M_PI clockwise:1];
//    anim.path = path.CGPath;
//时间
anim.duration = 3;
//重复次数
anim.repeatCount = INT_MAX;
[self.layer addAnimation:anim forKey:nil];
复制代码

组动画

  • 一次添加多个动画效果
//组动画
CAAnimationGroup *group = [CAAnimationGroup new];

//基本动画 自己旋转
CABasicAnimation *anim = [CABasicAnimation new];
anim.keyPath = @"transform.rotation";
anim.byValue = @(2 * M_PI * 10);

//关键帧动画
CAKeyframeAnimation *anim1 = [CAKeyframeAnimation new];
anim1.keyPath = @"position";
//路径动画
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150) radius:100 startAngle:0 endAngle:2 * M_PI clockwise:1];
anim1.path = path.CGPath;
group.animations = @[anim, anim1];
group.duration = 3;
group.repeatCount = INT_MAX;

[self.layer addAnimation:group forKey:nil];
复制代码

转场动画

  • view的转场
  • 需要设置动画方式和方向
  • 下面是配合手势实现的,手势也在下面整理
- (IBAction)imageChange:(UISwipeGestureRecognizer *)sender {
    NSLog(@"UISwipeGestureRecognizer");
    CATransition *anim = [CATransition new];
    //动画方式
    //官方方式
    //`fade', `moveIn', `push' and `reveal'. Defaults to `fade'
    //私有,有些有效果有些没效果
    //@"cube"、@"suckEffect"、@"oglFlip"、@"rippleEffect"、@"pageCurl"、@"pageUnCurl"、@"cameraIrisHollowOpen"、@"cameraIrisHollowClose"
    anim.type = @"push";
    if (sender.direction == UISwipeGestureRecognizerDirectionRight) {
        self.imageName --;
        if (self.imageName == 0) {
            self.imageName = 6;
        }
        //方向
        anim.subtype = kCATransitionFromLeft;
        NSLog(@"UISwipeGestureRecognizerDirectionRight");
    }
    else if (sender.direction == UISwipeGestureRecognizerDirectionLeft)
    {
        self.imageName ++;
        if (self.imageName == 7) {
            self.imageName = 1;
        }
        anim.subtype = kCATransitionFromRight;
        NSLog(@"UISwipeGestureRecognizerDirectionLeft");
    }
    
    self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld", self.imageName]];
    //转场动画
    anim.duration = 1;
    [self.imageView.layer addAnimation:anim forKey:nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.imageName = 1;
}
复制代码

手势识别

实现步骤

  1. 创建手势对象
  2. 对某一个view添加手势
  3. 实现手势方法

敲击

  • 手势方法
- (void)tap:(UITapGestureRecognizer *)sender
{
    NSLog(@"UITapGestureRecognizer");
}
复制代码
  • 实现
/**
 @property (nonatomic) NSUInteger  numberOfTapsRequired;       // 连续点击的次数
 @property (nonatomic) NSUInteger  numberOfTouchesRequired API_UNAVAILABLE(tvos);    // 手指个数
 */
 //创建手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
tap.numberOfTapsRequired = 2;
tap.numberOfTouchesRequired = 2;
//对某一个view添加手势
[self.imageView addGestureRecognizer:tap];
复制代码

长按

  • 手势方法
-(void)longPress:(UILongPressGestureRecognizer *)sender
{
    //UIGestureRecognizerStateEnded 松开
    //UIGestureRecognizerStateBegan 按下达到最小时间
    if (sender.state == UIGestureRecognizerStateChanged) {
        NSLog(@"UILongPressGestureRecognizer");
    }
}
复制代码
  • 实现
/**
 @property (nonatomic) NSTimeInterval minimumPressDuration; //响应时间
 @property (nonatomic) CGFloat allowableMovement; //误差范围
 @property(nonatomic,readonly) UIGestureRecognizerState state; //状态判断
 */
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
[self.imageView addGestureRecognizer:longPress];
longPress.minimumPressDuration = 1;
longPress.allowableMovement = 100;
复制代码

轻扫

  • 手势方法
-(void)swipe:(UISwipeGestureRecognizer *)sender
{
    if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {
        NSLog(@"UISwipeGestureRecognizer --- right");
    }
    else if (sender.direction == UISwipeGestureRecognizerDirectionRight) {
        NSLog(@"UISwipeGestureRecognizer --- left");
    }
}
复制代码
  • 实现
/**
 @property(nonatomic) UISwipeGestureRecognizerDirection direction; //方向
 */
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
[self.imageView addGestureRecognizer:swipe];
UISwipeGestureRecognizer *swipe1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
swipe1.direction = UISwipeGestureRecognizerDirectionLeft;
[self.imageView addGestureRecognizer:swipe1];
复制代码

旋转

  • 手势方法
-(void)rotation:(UIRotationGestureRecognizer *)sender
{
    self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, sender.rotation);
    //累加进行,要进行复原
    sender.rotation = 0;
    NSLog(@"UIRotationGestureRecognizer");
}
复制代码
  • 实现
/**
 @property (nonatomic)          CGFloat rotation;            // 旋转角度
 */
UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
[self.imageView addGestureRecognizer:rotation];
复制代码

捏合

  • 手势方法
-(void)pinch:(UIPinchGestureRecognizer *)sender
{
    self.imageView.transform = CGAffineTransformScale(self.imageView.transform, sender.scale, sender.scale);
    //累加进行,每次完成要复原
    sender.scale = 1;
    NSLog(@"UIPinchGestureRecognizer");
}
复制代码
  • 实现
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
[self.imageView addGestureRecognizer:pinch];
复制代码

拖拽

  • 手势方法
-(void)pan:(UIPanGestureRecognizer *)sender
{
    CGPoint p = [sender translationInView:sender.view];
    self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, p.x, p.y);
    [sender setTranslation:CGPointZero inView:sender.view];
    NSLog(@"UIPanGestureRecognizer");
    NSLog(@"%.f", sender.view.frame.origin.x);
}
复制代码
  • 实现
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self.imageView addGestureRecognizer:pan];
复制代码

多个手势同时添加

  • 通过UIGestureRecognizerDelegate代理方法实现
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 2;
tap.delegate = self;
[self.imageView addGestureRecognizer:tap];

UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];
[self.imageView addGestureRecognizer:rotation];
rotation.delegate = self;

UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];
[self.imageView addGestureRecognizer:pinch];
pinch.delegate = self;
复制代码
  • 解决手势冲突
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}
复制代码

触摸事件

  • 监听触摸功能

touches参数

window 触摸所在的窗口
view 触摸的视图
tapCount 短时间内点击的次数
timestamp 触摸事件变化的时间,时间戳形式(秒)
phase 触摸事件
复制代码

touches获取坐标

  • 以参数为坐标系的触摸当前坐标
UITouch *t = touches.anyObject;
//下面是以父控件为坐标系
CGPoint p = [t locationInView:self.superview];
//下面是以自己为坐标系
CGPoint p1 = [t locationInView:self];
NSLog(@"%@", NSStringFromCGPoint(p));
NSLog(@"%@", NSStringFromCGPoint(p1));
复制代码
  • 以参数为坐标系的触摸的上一个点的坐标
UITouch *t = touches.anyObject;
CGPoint p = [t previousLocationInView:self];
复制代码

触摸事件状态

  • cancelled,当触摸被取消(比如触摸过程中被来电打断)
  • 其他三个如字面意思
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
}
复制代码

未完

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享