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:來忽略動畫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章