iOS-AutoLayout中動畫使用的細節 和 iOS layout機制

 

 

在Main.storyboard拖入一個UIView,隨便設置一個背景色,app

使用autolayout  爲紫色的view添加約束 :(0,0,100,100) ,iphone

爲該view添加動畫代碼以下:異步

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *blueViewTop;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *blueViewLeading;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.blueViewTop.constant += 80;
    self.blueViewLeading.constant += 80;
    
    [UIView animateWithDuration:4 animations:^{
        //[self.view layoutIfNeeded];
    }];
}

 

這種方式下並無動畫效果.由於約束並非直接影響圖形的位置,設置完畢後系統會根據約束來計算圖形的位置和大小ide

因此當若是想修改約束實現動畫效果的話,須要在動畫代碼外邊調整約束,在動畫代碼內部調用layoutIfNeeded方法,該方法表示按照約束從新佈局界面 ;即增長[self.view layoutIfNeeded];oop


 

有時,在寫程序時,例如:佈局

tableView的使用時,先設定一個heightForHeader的高度,再自定義一個HeaderView來顯示自行定義內容時,咱們須要重寫initWithReuseIdentifier方法;動畫

 

//設定heightForHeader的高度atom

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{spa

    return 50;3d

}


 

當實例化一個HeaderView: [HeaderViewalloc]initWithReuseIdentifier:kIndentifer];

在重寫自定義的HeaderView的方法initWithReuseIdentifier時,設置自定義HeaderView內部數據時,咱們須要先調用才能實現對內部數據的設置

#pragma mark -

#pragma mark - layoutSubviews

-(void)layoutSubviews{

    [superlayoutSubviews];

    _headerButton.frame =self.contentView.frame;

    [selfsetupUIDate];

}



 

 



那麼,咱們的UIView到底是怎麼 ,什麼時候纔對其子view進行佈局的呢,佈局的機制又是什麼?

 

iOS layout機制相關的這幾個方法:

- (CGSize)sizeThatFits:(CGSize)size

- (void)sizeToFit


 

- (void)setNeedsLayout;

- (void)layoutIfNeeded;


- (void)layoutSubviews;   // override point. called by layoutIfNeeded automatically. As of iOS 6.0, when constraints-based layout is used the base implementation applies the constraints-based layout, otherwise it does nothing.



- (void)setNeedsDisplay

- (void)drawRect

首先須要明白layoutSubviews在如下狀況下會被調用:

 

一、init初始化不會觸發layoutSubviews。

二、addSubview會觸發layoutSubviews。

三、設置view的Frame會觸發layoutSubviews,固然前提是frame的值設置先後發生了變化。

四、滾動一個UIScrollView會觸發layoutSubviews。

五、旋轉Screen會觸發父UIView上的layoutSubviews事件。

六、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件。

七、直接調用setLayoutSubviews。

八、直接調用setNeedsLayout。


也就是說layoutSubviews, 當咱們在某個類的內部調整子視圖位置時,須要調用

在使用時,須要需注意:

 

-layoutSubviews方法:這個方法,默認沒有作任何事情,須要子類進行重寫

-setNeedsLayout方法: 標記爲須要從新佈局,異步調用layoutIfNeeded刷新佈局,不當即刷新,但layoutSubviews必定會被調用

-layoutIfNeeded方法:若是,有須要刷新的標記,當即調用layoutSubviews進行佈局(若是沒有標記,不會調用layoutSubviews)

若是要當即刷新,要先調用[view setNeedsLayout],把標記設爲須要佈局,而後立刻調用[view layoutIfNeeded],實現佈局


 

其次drawRect在如下狀況下會被調用:

一、若是在UIView初始化時沒有設置rect大小,將直接致使drawRect不被自動調用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 兩方法以後掉用的.因此不用擔憂在 控制器中,這些View的drawRect就開始畫了.這樣能夠在控制器中設置一些值給View(若是這些View draw的時候須要用到某些變量 值).

二、該方法在調用sizeToFit後被調用,因此能夠先調用sizeToFit計算出size。而後系統自動調用drawRect:方法。

sizeToFit會自動調用sizeThatFits方法;

sizeToFit不該該在子類中被重寫,應該重寫sizeThatFits

sizeThatFits傳入的參數是receiver當前的size,返回一個適合的size

sizeToFit能夠被手動直接調用

sizeToFit和sizeThatFits方法都沒有遞歸,對subviews也不負責,只負責本身

三、經過設置contentMode屬性值爲UIViewContentModeRedraw。那麼將在每次設置或更改frame的時候自動調用drawRect:。

四、直接調用setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,可是有個前提條件是rect不能爲0。

-setNeedsDisplay方法:標記爲須要重繪,異步調用drawRect

-setNeedsDisplayInRect:(CGRect)invalidRect方法:標記爲須要局部重繪


須要注意的是:

 

drawRect方法使用注意點:

一、 若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef並繪圖。若是在其餘方法中獲取將獲取到一個invalidate 的ref而且不能用於畫圖。drawRect:方法不能手動顯示調用,必須經過調用setNeedsDisplay 或 者 setNeedsDisplayInRect,讓系統自動調該方法。

二、若使用calayer繪圖,只能在drawInContext: 中(相似魚drawRect)繪製,或者在delegate中的相應方法繪製。一樣也是調用setNeedDisplay等間接調用以上方法

三、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時刷新屏幕


 


layoutSubviews對subviews從新佈局

layoutSubviews方法調用先於drawRect

setNeedsLayout在receiver標上一個須要被從新佈局的標記,在系統runloop的下一個週期自動調用layoutSubviews

layoutIfNeeded方法如其名,UIKit會判斷該receiver是否須要layout.根據Apple官方文檔,layoutIfNeeded方法應該是這樣的

layoutIfNeeded遍歷的不是superview鏈,應該是subviews

drawRect是對receiver的重繪,能得到context

setNeedDisplay在receiver標上一個須要被從新繪圖的標記,在下一個draw週期自動重繪,iphone device的刷新頻率是60hz,也就是1/60秒後重繪

相關文章
相關標籤/搜索