此方法用來重新定義子元素的位置和大小。當子類重寫此方法,用來實現UI元素的更精確布局。如果要讓布局重新刷新,那么就調用setNeedsLayout,即setNeedsLayout方法會默認用layoutSubViews方法。
很多時候系統會自動調用layoutSubviews方法:
1.初始化不會觸發layoutSubviews,但是如果設置了不為CGRectZero的frame的時候就會觸發。
2.addSubview會觸發layoutSubviews
3.設置view的Frame會觸發layoutSubviews,當然前提是frame的值設置前后發生了變化
4.滾動一個UIScrollView會觸發layoutSubviews
5.旋轉Screen會觸發父UIView上的layoutSubviews事件
6.改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件
注:setNeedsLayout方法並不會立即刷新,立即刷新需要調用layoutIfNeeded方法。
延伸:
當我們自定義UI控件時,需要重寫一些方法:
UIView控件只是一個矩形的空白區域並沒有任何內容。iOS應用的其他UI控件都繼承了UIView這些UI控件都是在UIView提供的空白區域上繪制外觀。
基於UI控件的實現原理開發者完全可以開發出項目定制的控件——當iOS系統提供的UI控件不足以滿足項目需要時開發者可以通過繼承UIView來派生自定義控件。
當開發者打算派生自己的UI控件時首先定義一個繼承View基類的子類然后重寫View類的一個或多個方法通常可以被用戶重寫的方法如下。
initWithFrame:前面已經見到程序創建UI控件時常常會調用該方法執行初始化因此如果你需要對UI控件執行一些額外的初始化即可通過重寫該方法來實現。
initWithCoder:程序通過在nib文件中加載完該控件后會自動調用該方法。因此如果程序需要在nib文件中加載該控件后執行自定義初始化則可通過重寫該方法來實現。
drawRect:如果程序需要自行繪制該控件的內容則可通過重寫該方法來實現。
layoutSubviews如果程序需要對該控件所包含的子控件布局進行更精確的控制可通過重寫該方法來實現。
didAddSubview:當該控件添加子控件完成時將會激發該方法。
willRemoveSubview:當該控件將要刪除子控件時將會激發該方法。
willMoveToSuperview:當該控件將要添加到其父控件中時將會激發該方法。
didMoveToSuperview當把該控件添加到父控件完成時將會激發該方法。
willMoveToWindow: 當該控件將要添加到窗口中時將會激發該方法。
didMoveToWindow當把該控件添加到窗口完成時將會激發該方法。
touchesBegan:withEvent:當用戶手指開始觸碰該控件時將會激發該方法。
touchesMoved:withEvent:當用戶手指在該控件上移動時將會激發該方法。
touchesEnded:withEvent:當用戶手指結束觸碰該控件時將會激發該方法。
touchesCancelled:withEvent:用戶取消觸碰該控件時將會激發該方法。
當需要開發自定義View時開發者並不需要重寫上面列出的所有方法而是根據業務需要重寫上面的部分方法。例如下面的跟隨手指運動的小球示例程序就只重寫drawRect:方法。
#import "FKCustomView.h"
@implementation FKCustomView
// 定義兩個變量記錄當前觸碰點的坐標
int
curX;
int
curY;
- (
void
) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// 獲取觸碰事件的UITouch事件
UITouch *touch = [touches anyObject];
// 得到觸碰事件在當前組件上的觸碰點
CGPoint lastTouch = [touch locationInView:self];
// 獲取觸碰點的坐標
curX = lastTouch.x;
curY = lastTouch.y;
// 通知該組件重繪
[self setNeedsDisplay];
}
// 重寫該方法來繪制該UI控件
- (
void
)drawRect:(CGRect)rect
{
// 獲取繪圖上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 設置填充顏色
CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);
// 以觸碰點為圓心繪制一個圓形
CGContextFillEllipseInRect(ctx, CGRectMake(curX - 10, curY - 10, 20, 20));
}
@end