iOS手势和动画| 青训营笔记

330 阅读4分钟

这是我参与「第四届青训营 -iOS场」笔记创作活动的的第5篇笔记

交互与手势

  1. UITapGestureRecognizer 点按
  2. UILongPressGestureRecognizer 长按
  3. UISwipeGestureRecognizer 轻扫
  4. UIRotationGestureRecognizer 旋转
  5. UIPinchGestureRecognizer 捏合
  6. UIPanGestureRecognizer 拖拽
  • 通过UIGestureRecognizerDelegate,可以约束手势响应时机

image.png

手势原理

  • iOS交互事件
  1. 触摸事件
  2. 运动事件
  3. 远程事件
  • UITouch,抽象了手指触摸屏幕的一个类,每一个实例代表手指的一次处理,携带位置、大小等信息
  1. 根据上下文信息,生成UIEvent对象,抽象了由一个或者多个UITouch所造成的一个事件;每一个实例代表一个触摸事件,比如单击事件,长按事件
  2. 生成之后,将UITouch和UIEvent发送给UIResponder,进行响应和处理事件;当有事件发生,系统会去寻找最合适的UIResponder,进行通知
  3. 收到事件后,App将Event发送给keyWindow(根视图),由根视图开始遍历查找响应者视图 image.png
  4. UIView通过hitTest:withEvent判断响应者,通过userInteractionEnabled(是否能交互)、hidden(是否被隐藏)、alpha(透明度是否为0)判断自身是否能响应;pointInside:withEvent判断触摸点是否在自己frame范围内;从后往前依次递归子视图,如果都没有就返回自己

动画

block动画

  • 基本使用
UIView *animationView = [[UIView alloc] initWithFrame:CGRectMake(5, 5, 100, 100)];
animationView.backgroundColor = [UIColor redColor];
[self.view addSubview:animationView];
[UIView animateWithDuration:3 animations:^{
    CGRect frame = animationView.frame;
    frame.size = CGSizeMake(200, 200);
    frame.origin = CGPointMake(20, 20);
    animationView.frame = frame;
    animationView.backgroundColor = [UIColor blueColor];
}];
  • 完成后再变换
[UIView animateWithDuration:4 animations:^{
    CGRect frame = animationView.frame;
    frame.size = CGSizeMake(200, 200);
    frame.origin = CGPointMake(20, 20);
    animationView.frame = frame;
    animationView.backgroundColor = [UIColor blueColor];
} completion:^(BOOL finished) {
    [UIView animateWithDuration:3 animations:^{
        animationView.backgroundColor = [UIColor blackColor];
        animationView.transform = CGAffineTransformMakeRotation(M_PI_2);
    }];
}];
  • options
  1. UIViewAnimationOptionRepeat 重复执行
  2. UIViewAnimationCurveEaseInOut 缓入缓出
  3. UIViewAnimationOptionAutoreverse 自动反转
  • 弹簧效果
  1. usingSpringWithDamping 弹簧弹力 0~1 0的时候弹力最大
  2. initialSpringVelocity 弹簧动画初始速度,取值越大,初始变化越大
[UIView animateWithDuration:3 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:5 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
    animationView.backgroundColor = [UIColor blackColor];
    animationView.transform = CGAffineTransformMakeRotation(M_PI_2);
} completion:nil];
  • 关键帧动画
  1. addKeyframeWithRelativeStartTime 0~1 哪个比例开始
  2. relativeDuration 0~1 持续多久的比例
[UIView animateKeyframesWithDuration:3 delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
    // 添加关键帧
    [UIView addKeyframeWithRelativeStartTime: 0 relativeDuration:0.3 animations:^{
        CGRect frame = animationView.frame;
        frame.size = CGSizeMake(200, 200);
        frame.origin = CGPointMake(20, 20);
        animationView.frame = frame;
    }];
    [UIView addKeyframeWithRelativeStartTime: 0.3 relativeDuration:0.3 animations:^{
        animationView.backgroundColor = [UIColor blueColor];
    }];
    [UIView addKeyframeWithRelativeStartTime: 0.6 relativeDuration:0.4 animations:^{
        animationView.transform = CGAffineTransformMakeRotation(M_PI_2);
    }];
} completion:^(BOOL finished) {
}];
  • 转场动画,整个view,从某个方向转场成另一个
// transitionFromView时的option 设置多个没什么用
UIViewAnimationOptionTransitionNone 
// 从左右翻转
UIViewAnimationOptionTransitionFlipFromLeft  
UIViewAnimationOptionTransitionFlipFromRight
// 翻页
UIViewAnimationOptionTransitionCurlUp         
UIViewAnimationOptionTransitionCurlDown
// 渐入渐出
UIViewAnimationOptionTransitionCrossDissolve
// 从上下翻转
UIViewAnimationOptionTransitionFlipFromTop
UIViewAnimationOptionTransitionFlipFromBottom
// from - to
[UIView transitionFromView:self.newView toView:self.animationView duration:3 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {

}];
// 单独的animationView的变化
[UIView transitionWithView:self.animationView duration:3 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{
    CGRect frame = self.animationView.frame;
    frame.size = CGSizeMake(200, 200);
    frame.origin = CGPointMake(20, 20);
    self.animationView.frame = frame;
        } completion:^(BOOL finished) {
}];

核心动画

  • basic
// 指定keypath,作为动画指标,也就是layer的属性
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
basicAnimation.duration = 3;
basicAnimation.repeatCount = 3;
basicAnimation.fromValue = [NSNumber numberWithFloat:0.0];
basicAnimation.toValue = [NSNumber numberWithFloat: M_PI * 0.3];
// 不回到原始位置
basicAnimation.fillMode = kCAFillModeForwards;
basicAnimation.removedOnCompletion = NO;
// 可以根据key进行remove
[animationView.layer addAnimation:basicAnimation forKey:@"demo"];
  • keyframe
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];
//时间
anim.duration = 3;
//重复次数
anim.repeatCount = INT_MAX;
[animationView.layer addAnimation:anim forKey:@"demo"];
  • 路径动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation new];
anim.keyPath = @"position";
// 路径动画
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;
[animationView.layer addAnimation:anim forKey:@"demo"];
  • 组动画
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;
[animationView.layer addAnimation:group forKey:@"demo"];

Lottie

  • 动画库,实现复杂的动画,就是个单单的动画,是额外的LOTAimationView控件
  • 设计师导出json文件,调用接口即可呈现
  • pod lottie-ios

UIDynamicAnamitor

  • 仿真物理学动画
  • 类别
  1. UIGravityBehavior 重力
  2. UICollisionBehavior 碰撞
  3. UIAttachmentBehavior 附着
  4. UISnapBehavior 吸附
  5. UIPushBehavior 推力
  6. UIFieldBehavior 场力
  • UIDynamicAnamitor
  1. UIDynamicItem,动力学元素,一个遵守动力学协议的控件
  2. UIDynamicBehavior,仿真行为,持有UIDynamicItem数组,赋予item这个行为或者唤醒
  3. UIDynamicAnimator,仿真动画者,执行动画
  • 使用
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 0, 30, 30)];
view.layer.cornerRadius = 15;
view.backgroundColor = [UIColor redColor];
[self.view addSubview:view];
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[view]];
gravity.magnitude = 5;
[self.animator addBehavior:gravity];
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[view]];
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];