ios CATransaction事务动画,键盘弹出和消失视图变化

ios的动画的技术方案很多,UIview、CoreAnimation,

(1)在UIview的分类中的的类方法中有+animationWithDuration:及其它类似的方法,可以实现一些比较基础的动画可以对UIview的属性使用,如frame、backgroundColor等

(2)CoreAnimation框架中CAAnimation类的子类,CABasicAnimation、CAPropertyAnimation、CAKeyFrameAnimation实现强大的动画。

(3)基于CADisplayLink的动画,与CoreGraphic结合也可以实现动画效果。

隐式事务

隐式动画是基于CALayer层的,UIKit框架是禁用隐式事务动画的,UIview与CALayer的关系,UIView是负责交互而CALayer是负责显示图层的。

隐式事务是CoreAnimation的一部分,是对layer-tree进行原子更新为render-tree的机制,由CoreAnimation来帮助自动创建完事务,当前线程的runloop下次循环就会自动commit,如果当前线程没有runloop,或者runloop被阻塞,则应该显示的创建显示事务。手动创建CATransaction动画事务。

@property(nonatomic,strong)CALayer *testLayer;

-(void)viewDidLoad{
    [super viewDidLoad];

    self.testLayer = [CALayer layer];
    self.testLayer.frame = CGRectMake(50, 100, 100, 100);
    self.testLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.testLayer];
}


-(void)buttonClick{
    //会有一闪而过的动画,隐式动画
    self.testLayer.backgroundColor = [UIColor blueColor].CGColor;
}

//显示动画
-(void)buttonClick{
    //1.开启显示事务
    [CATransaction begin];
    NSLog(@"=====start");
    //2.设置动画时间
    [CATransaction setAnimationDuration:2];
    //4.设置回调
    [CATransaction setCompletionBlock:^{
        //5.也可以嵌套事务
        //背景色改变后,改变圆角
        [CATransaction setAnimationDuration:1];
        self.testLayer.cornerRadius = 10;
        NSLog(@"=====end");
    }];
    self.testLayer.backgroundColor = [UIColor blueColor].CGColor;
     NSLog(@"=====....");
    //3.提交事务
    [CATransaction commit];
}

CALayer可以对事务动画做出相应是因为CALayer的实例方法-actionForKey:可以对其进行相应,返回对应的方法。

但是对于UIView来说,UIview作为CAlayer的代理,则根据名称来获取action对象,会遵循以下顺序

1.如果view有代理,则调用代理方法-actionForLayer:forKey

2.检查layer的actions字典

3.检查layer的style层级中每个actions字典

4.调用layer的类方法+defaultActionForKey

代理方法

-(id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event{
    NSLog(@"event=%@",event,);
    return layer.actions[event];
}

打印

2019-09-27 11:12:38.863194+0800 CADemo[61157:1358546] event=backgroundColor
2019-09-27 11:12:38.865429+0800 CADemo[61157:1358546] event=onOrderIn
2019-09-27 11:12:38.870547+0800 CADemo[61157:1358546] event=onLayout
2019-09-27 11:12:41.174068+0800 CADemo[61157:1358546] =====start
2019-09-27 11:12:41.175396+0800 CADemo[61157:1358546] event=backgroundColor
2019-09-27 11:12:41.176373+0800 CADemo[61157:1358546] =====....
2019-09-27 11:12:43.177419+0800 CADemo[61157:1358546] event=cornerRadius
2019-09-27 11:12:43.177659+0800 CADemo[61157:1358546] =====end

启动时会触发-actionForLayer:forKey这个代理方法

当点击按钮,开始事务动画时,触发代理方法,首先执行backgroundColor这个动画,然后再修改圆角。

应用

监听键盘,上移被遮挡的View

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.defalutRect = self.textField.frame;
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    
       [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHiden:) name:UIKeyboardWillHideNotification object:nil];


}

-(void)keyboardWillShow:(NSNotification *)noti{
    NSLog(@"noti.userInfo=%@",noti.userInfo);
    
    NSDictionary*info=[noti userInfo];

    CGRect rect=[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];  //键盘上移后的frame

    CGRect textFrame =  self.textField.frame;
    
    //键盘与textfiled会紧贴
//    textFrame.origin.y = rect.origin.y -textFrame.size.height -1 ;
    
    // 键盘与textfiled不会紧贴,会有原先与底部的距离
    textFrame.origin.y = textFrame.origin.y - rect.size.height;
    self.textField.frame = textFrame;
    self.textField.delegate = self;
    self.textField.returnKeyType =  UIReturnKeyDone;
}

-(void)keyboardWillHiden:(NSNotification *)noti{
    NSLog(@"noti.userInfo=%@",noti.userInfo);
    self.textField.frame =  self.defalutRect;
}

NSNotification的userInfo中存储了键盘与frame相关的信息。

UIKeyboardFrameBeginUserInfoKeyUIKeyboardFrameEndUserInfoKey对应的是键盘在进行交互前和和交互后的frame,没有交互前的是在屏幕底部,且根据UIKeyboardAnimationDurationUserInfoKey 对应的是动画持续的时间,所以这里键盘弹出是由一个0.25s的动画。

那么如何开启和关闭这个动画呢?

-(void)keyboardWillShow:(NSNotification *)noti{
    
    [UIView setAnimationsEnabled:NO];

    //do something

    //关闭后记得打开
    [UIView setAnimationsEnabled:YES];
}

通过UIview的类方法+setAnimationsEnabled:来忽略动画。

发布了47 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/a1034386099/article/details/101515988
今日推荐