UIView(控件)
UIView的創(chuàng)建
-
alloc init
方法創(chuàng)建
- 通過
UIStoryboard加載
控件詳見UIStoryboard - 通過
xib加載
控件詳見XIB
UIView的常用屬性
// superview:獲得自己的父控件對象,每個子控件的superview只有一個,該屬性只讀
// 一般用于判斷是否已經(jīng)加入到視圖中同辣,避免重復(fù)添加
if (view.superview) return;
// subviews:獲得自己的所有子控件對象,只讀
NSLog(@"%@",view.subviews);
// 是否可與用戶交互
view.userInteractionEnabled = YES;
// 裁剪超出范圍的控件
view.clipsToBounds = YES;
// 設(shè)置透明度
view.alpha = 1;
// 設(shè)置背景顏色,默認(rèn)是clearColor
view.backgroundColor = [UIColor colorWithRed:1 green:1 blue:0 alpha:0.3];//顏色由三原色組成
- [UIView 屬性解析大全][http://www.reibang.com/p/4baf286f4bc1]
UIView的常用方法
// 添加一個子控件view
// 底層實現(xiàn):
// 1.判斷傳入view之前有沒有父控件
// 2.如果有,先移除之前父控件
// 3.再重新添加view
[self.view addSubview:view];
// 從父控件中移除
// 多用于動畫控件完成動畫后移除
[self.view removeFromSuperview];
UIView獲取子控件或其標(biāo)識
- 開發(fā)中惭载,經(jīng)常需要使用到標(biāo)識來獲取控件或其標(biāo)識旱函,用于控件間的聯(lián)動,這時的可選方案如下:
-
方案一:通過tag值(不推薦使用)
- tag:控件的ID(標(biāo)識)描滔,父控件可以通過tag來找到對應(yīng)的子控件;
- tag默認(rèn)值是0
- tag值是隨意設(shè)置棒妨,很容易混亂,能不用就不用含长,開發(fā)時間越長券腔,tag值管理會越來越困難
// 設(shè)置tag值 view.tag = 10; // 根據(jù)tag獲取view,沒找到返回nil UIView *view = [self.view viewWithTag:10]; // viewWithTag:內(nèi)部的大致實現(xiàn)思路 - (UIView *)viewWithTag:(NSInteger)tag { if (self.tag == tag) return self; for (UIView *subview in self.subviews) { // 返回tag標(biāo)識找出對應(yīng)的控件(一般都是子控件) return [subview viewWithTag:tag]; } }
-
方案二:通過subviews數(shù)組獲染信ⅰ(不推薦)
- 不足:一般都是通過控制器的view的subviews獲取子控件或其標(biāo)識纷纫,但該view不僅有我們自己創(chuàng)建的控件,也有系統(tǒng)創(chuàng)建的控件陪腌,不好把握辱魁,容易出錯;另外子元素種類一般不相同烟瞧,不方便管理
// 獲取某個子控件 UIView *view = self.view.subviews[0]; // 獲取控件標(biāo)識 NSInteger index = [self.views indexOfObject:view]
- 不足:一般都是通過控制器的view的subviews獲取子控件或其標(biāo)識纷纫,但該view不僅有我們自己創(chuàng)建的控件,也有系統(tǒng)創(chuàng)建的控件陪腌,不好把握辱魁,容易出錯;另外子元素種類一般不相同烟瞧,不方便管理
-
方案三:新建數(shù)組,獲取角標(biāo)獲取控件(推薦方案)
// 新建控件數(shù)組并作為成員屬性 NSMutableArray *views = [NSMutableArray array]; self.views = views; // 將控件添加到控件數(shù)組中 [self.views addObject:view]; [self.views addObject:view1]; [self.views addObject:view2]; // 獲取控件標(biāo)識 NSInteger index = [self.views indexOfObject:view] // 獲取控件 UIView *view = self.views[index];
-
UIViewContentMode屬性(只對UIImageView控件中圖片有效)
- 帶有
scale
單詞的:圖片有可能會拉伸(常用)
含scale 的屬性 |
拉伸方式(不旋轉(zhuǎn)圖片 ) |
保持原寬高比染簇? | 備注 |
---|---|---|---|
UIViewContentModeScale ToFill |
不按比例拉伸 拉伸圖片至填充整個控件 |
否 | 圖片跟控件同寬同高 燕刻;默認(rèn)屬性
|
UIViewContentModeScaleAspect Fill |
按比例拉伸 圖片,直至圖片拉伸至填充整個控件 |
是 | 圖片一邊與控件相等剖笙,另一邊大 于控件 |
UIViewContentModeScaleAspect Fit |
按比例拉伸 圖片,直至圖片任一邊與控件對應(yīng)邊一樣大 |
是 | 圖片一邊與控件相等请唱,另一邊小 于控件 |
- 沒有
scale
單詞的:圖片絕對不會被拉伸
不含scale 的屬性 |
是否拉伸 | 在控件中的顯示位置 |
---|---|---|
UIViewContentModeCenter | 保持圖片的原尺寸 | 居中 |
UIViewContentModeTop | 同上 | 上面 |
UIViewContentModeBottom | 同上 | 下面 |
UIViewContentModeLeft | 同上 | 左面 |
UIViewContentModeRight | 同上 | 右面 |
UIViewContentModeTopLeft | 同上 | 左上 |
UIViewContentModeTopRight | 同上 | 右上 |
UIViewContentModeBottomLeft | 同上 | 左下 |
UIViewContentModeBottomRight | 同上 | 右下 |
UIView的封裝(自定義控件)
- 自定義控件基礎(chǔ):父子控件
1. 每個控件都是個容器弥咪,能容納其他控件
1. 內(nèi)部小控件是大控件的子控件
2. 大控件是內(nèi)部小控件的父控件
-
自定義控件的意義
1. 如果一個view內(nèi)部的子控件比較多,一般會考慮自定義一個view十绑,把它內(nèi)部子控件的創(chuàng)建屏蔽起來聚至,不暴露給外界2. 外界可以傳入對應(yīng)的模型數(shù)據(jù)給view,view拿到模型數(shù)據(jù)后給內(nèi)部的子控件設(shè)置對應(yīng)的數(shù)據(jù)
-
步驟:
- 新建一個繼承
UIView
的類
- 創(chuàng)建并布局子控件(純代碼或者xib方式)
純代碼方式
1. 提供類方法及對象方法
1. 可以重寫init或initWithFrame方法
2. 重寫init創(chuàng)建時本橙,底層也會調(diào)用initWithFrame方法扳躬,先調(diào)用父類的,再調(diào)用子類自身甚亭;
2. 在initWithFrame:方法中添加并初始化子控件
3. 在layoutSubviews方法中布局子控件贷币,布局前必須調(diào)用[super layoutSubviews];xib方式
1. 新建一個xib文件(xib的文件名最好跟控件類名一樣)
1. 添加子控件、設(shè)置子控件屬性
2. 修改最大的父控件的class為控件類名
3. 將子控件進行連線
2. 提供一個類方法及對象方法用于加載xib
1. 初始化時底層不調(diào)用initWithFrame:方法亏狰,而是調(diào)用`initWithCoder:方法役纹。加載時:
2. initWithCoder是第一個執(zhí)行的方法
3. awakeAfterUsingCoder:是第二個執(zhí)行的方法
3. awakeFromNib是最后執(zhí)行的方法,可在這里初始化控件
- 提供
模型屬性
暇唾,重寫模型屬性的set
方法- 在set方法中給子控件設(shè)置數(shù)據(jù)
- 新建一個繼承
漸變式動畫
- 頭尾式
// 開始動畫 [UIView beginAnimations:nil context:nil]; // 設(shè)置動畫屬性 // 設(shè)置動畫時間 [UIView setAnimationDuration:2.0]; /* 需要執(zhí)行動畫的代碼 */ // 提交動畫 [UIView commitAnimations];
- block式(實質(zhì)是蘋果對頭尾式動畫的封裝)
// 在1秒內(nèi)執(zhí)行動畫 [UIView animateWithDuration:1.0 animations:^{ // 顯示指示版 self.hudLbl.alpha = 1;//不透明 } completion:^(BOOL finished) { // 上一個動畫完畢后延遲3秒后促脉,在1秒內(nèi)執(zhí)行下列動畫 [UIView animateWithDuration:1.0 delay:3.0 options:kNilOptions animations:^{ // 隱藏指示版 self.hudLbl.alpha = 0;//完全透明 } completion:nil]; }];
UIView界面跳轉(zhuǎn)
如果2個控件如果有重疊部分,那么處于上面的那個控件會蓋住下面的策州。上面的控件不是透明或顏色為clearColor瘸味,會擋住下面控件的顯示
開發(fā)中需要在某些時刻將指定的控件顯示出來,即放在最上面够挂;這時需要界面跳轉(zhuǎn)旁仿。
- 界面跳轉(zhuǎn)主要的方法有3種:
- 用 UINavigationController 把 View B push 進來。
[self.navigationController pushViewController:nextView animated:YES];
- 用Modal的 presentModalViewController 方法把 View B 蓋在上面下硕。
[self presentModalViewController:nextView animated:YES];
- 調(diào)整窗口subView中元素的順序丁逝,也可應(yīng)用于當(dāng)前顯示的父控件中,讓其某個子控件顯示出來;
// AppDelegate.m 類 // 添加到窗口上 [self.window addSubview:viewB]; [self.window addSubview:viewA]; // 調(diào)整控件位置順序梭姓,讓其顯示出來 [self.window bringSubviewToFront:viewB];
- 用 UINavigationController 把 View B push 進來。
- 界面跳轉(zhuǎn)的本質(zhì)重新調(diào)整窗口subViews中元素的順序霜幼,讓最后一個元素顯示
UIView圓角裁剪和加邊框方式
方案一 :最簡單的
// 最簡單的方式就是設(shè)置每個 View 自帶的 layer 的屬性即可
view.layer.cornerRadius = 8.0f;
// 如果該 View 有子 View,會是這種狀況
// 如果需要切掉除了保留部分以外的子 View誉尖,那么需要加上
view.clipsToBounds = YES;
// 如果需要邊框罪既,也簡單,加上 layer 的邊框設(shè)置就可以。
view.layer.borderWidth=10.0f;
view.layer.borderColor= [UIColor yellowColor].CGColor;
// 但是如果細(xì)看,會發(fā)現(xiàn)邊框有嚴(yán)重的黑邊问慎,特別是當(dāng) View 背景色比較深的時候
方案一總結(jié):
1.1 好處:簡單颈将,哪里需要圓角就在哪里設(shè)置就可以了。
1.2 缺點:這種方式處理的圓角很模糊烘挫,特別是在視圖比較小的時候,質(zhì)量不高柬甥,當(dāng)背景色比較深的時候有邊框有黑邊現(xiàn)象饮六,而且如果使用了 clipToBounds ,則會觸發(fā)離屏渲染(這個一個很大的坑苛蒲,有興趣的話可以詳細(xì)了解下)卤橄,造成很嚴(yán)重的卡頓問題,特別是在 UITableViewCell 的子 View 中這樣使用臂外,掉幀會很嚴(yán)重窟扑。
方案二 :設(shè)置 mask layer
// 使用貝賽爾曲線,并根據(jù)其路徑漏健,得到一個「遮罩 layer」嚎货,將其設(shè)置為 View 自帶 layer 的 mask,蓋掉其他部分蔫浆,剩余中間的部分厂抖。也可以達到圓角效果。
- (void)setRoundedCorners {
UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];
CAShapeLayer* maskLayer = [CAShapeLayerlayer];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
// 將這個 masklayer 加到自帶 layer 上而不是設(shè)置為其 mask克懊,代碼如下:
/*
UIBezierPath* maskPath = [UIBezierPath bezierPathWithRoundedRect:v.boundsbyRoundingCorners:UIRectCornerAllCornerscornerRadii:CGSizeMake(halfW, halfW)];
CAShapeLayer* maskLayer = [CAShapeLayer layer];
maskLayer.frame = view.bounds;
maskLayer.fillColor = [UIColor whiteColor].CGColor;
maskLayer.path = maskPath.CGPath;
maskLayer.backgroundColor= [UIColor greenColor].CGColor;
[view.layer addSublayer:maskLayer];
*/
// 效果圖:
// 一個只有四個角的 layer 蓋到原來的 layer 上忱辅,達到圓角效果。
// 因為是蓋住四角達到的效果谭溉,所以不用設(shè)置 maskToBounds 也可以去掉子 View 超出中心圓的部分墙懂,但是同樣會觸發(fā)離屏渲染。用的時候應(yīng)當(dāng)小心扮念。
```

```objc
// 如果要加上邊框损搬,可以在 self.layer 上加一個圓環(huán) layer 達到邊框效果,代碼如下:
- (void)setRoundedCorners:(UIRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor cornerSize:(CGSize)size {
UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:size];
CAShapeLayer* maskLayer = [CAShapeLayerlayer];
maskLayer.fillColor = [UIColorblueColor].CGColor;
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
if(borderWidth >0) {
CAShapeLayer*borderLayer = [CAShapeLayerlayer];
// 用貝賽爾曲線畫線柜与,path 其實是在線的中間巧勤,這樣會被 layer.mask(遮罩層)遮住一半,故在 halfWidth 處新建 path弄匕,剛好產(chǎn)生一個內(nèi)描邊
CGFloathalfWidth = borderWidth /2.0f;
CGRectf =CGRectMake(halfWidth, halfWidth,CGRectGetWidth(self.bounds) - borderWidth,CGRectGetHeight(self.bounds) - borderWidth);
borderLayer.path = [UIBezierPathbezierPathWithRoundedRect:f byRoundingCorners:corners cornerRadii:size].CGPath;
borderLayer.fillColor = [UIColorclearColor].CGColor;
borderLayer.strokeColor = borderColor.CGColor;
borderLayer.lineWidth = borderWidth;
borderLayer.frame = CGRectMake(0,0,CGRectGetWidth(f),CGRectGetHeight(f));
[self.layer addSublayer:borderLayer];
}
// 我們會看到這里 borderLayer 的坐標(biāo)很奇怪颅悉,這里解釋一下,如果我們這樣設(shè)置坐標(biāo)迁匠,用以下方式添加 borderLayer剩瓶,會是什么效果呢驹溃?
UIBezierPath* borderPath= [UIBezierPathbezierPathWithRect:v.bounds];
CAShapeLayer* borderLayer= [CAShapeLayer layer];
borderLayer.path =borderPath.CGPath;
borderLayer.fillColor = [UIColor clearColor].CGColor;
borderLayer.strokeColor = [[UIColorblackColor]colorWithAlphaComponent:0.5].CGColor;
borderLayer.lineWidth =10;
borderLayer.frame = v.bounds;
[v.layer addSublayer:borderLayer];
// 效果圖:
// 效果分析:
// 邊框剛好騎在了邊界上,如果這時候我們在使用 maskLayer 做圓角延曙,那騎在邊界上的邊框有外面一半將被吃掉豌鹤,只剩下一半,所以要把 borderLayer 往里挪一半的邊框的距離枝缔,避免讓 maskLayer 吃掉外面那部分邊框布疙。
放大后的效果圖:
方案二總結(jié):
1.1 好處:簡單,并且可以使用貝賽爾曲線達到任意形狀的「剪切」愿卸,也可以根據(jù)情況選擇要「切」的角拐辽,比如如果只需要切右上和右下兩個角,那么只需要改一下貝賽爾曲線
UIBezierPath* maskPath = [UIBezierPathbezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopRight|UIRectCornerBottomRightcornerRadii:CGSizeMake(halfW, halfW)];
1.2 缺點:上一種方式的缺點擦酌,這個方式也都有
方案三 :生成圓角背景圖片方式
CGFloat w = 200;
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0,0, w, w)];
v.backgroundColor= [UIColor redColor];
[self.view addSubview:v];
v.center = self.view.center;
UIImage *img = [UIImage imageWithColor:v.backgroundColorandSize:v.bounds.size];
img = [img roundedWithBorderWidth:10borderColor:[UIColorgreenColor]];
UIImageView *imageView = [[UIImageView alloc] initWithImage:img];
[v insertSubview:imageViewatIndex:0];
v.backgroundColor= [UIColor clearColor];
// 根據(jù) View 的大小和背景色,生成一張圖片菠劝,生成圖片的方法如下:
@implementationUIImage(ZQExtension)
+ (UIImage*)imageWithColor:(UIColor*)color andSize:(CGSize)size {
CGRectrect =CGRectMake(0.0f,0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size,NO, [UIScreenmainScreen].scale);
CGContextRefcontext =UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [colorCGColor]);
CGContextFillRect(context, rect);
UIImage*image =UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); returnimage;
}
@end
// 再將這張圖片圓角處理赊舶,并加上邊框,最后創(chuàng)建一個 UIImageView赶诊,設(shè)置該 imageView 的 image 為圓角處理后的圖片笼平,并插入 View 的最底層,造成一種圓角處理的假象舔痪。
// 圓角處理的代碼如下:
@implementationUIImage(ZQExtension)
- (UIImage*)roundedWithBorderWidth:(CGFloat)borderWidth borderColor:(UIColor*)borderColor {
CGFloatinset =1;
CGFloatwidth =self.size.width;
CGFloatheight =self.size.height;
CGFloatcornerRadius;
UIBezierPath*maskShape;
if(width > height) {
cornerRadius = height / 2.0- inset;
maskShape = [UIBezierPathbezierPathWithRoundedRect:CGRectMake((width-height)/2.0+ inset,0+ inset, height-2*inset, height-2*inset) cornerRadius:cornerRadius];
}else{
cornerRadius = width / 2.0- inset;
maskShape = [UIBezierPathbezierPathWithRoundedRect:CGRectMake(0+inset, (height-width)/2.0+inset, width-2*inset, width-2*inset) cornerRadius:cornerRadius];
}
UIGraphicsBeginImageContextWithOptions(self.size,NO, [UIScreenmainScreen].scale);
CGContextRefctx =UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextAddPath(ctx, maskShape.CGPath);
CGContextClip(ctx); CGContextTranslateCTM(ctx,0, height);
CGContextScaleCTM(ctx,1.0,-1.0);
CGContextDrawImage(ctx,CGRectMake(0,0, width, height),self.CGImage);
CGContextRestoreGState(ctx);
if(borderWidth >0) {
[borderColor setStroke];
CGFloathalfWidth = borderWidth /2.0;
UIBezierPath*border = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(halfWidth, halfWidth,self.size.width - borderWidth ,self.size.width - borderWidth)];
CGContextSetShouldAntialias(ctx,YES);
CGContextSetAllowsAntialiasing(ctx,YES);
CGContextSetLineWidth(ctx, borderWidth);
CGContextAddPath(ctx, border.CGPath);
CGContextStrokePath(ctx);
}
UIImage*resultingImage =UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
returnresultingImage;
} @end
// 效果如下:
// 這里使用貝賽爾曲線加邊框的坐標(biāo)和第二種方式的類似寓调。
方案三 :生成圓角背景圖片方式總結(jié)
3.1 好處:是不會觸發(fā)離屏渲染,生成圖片和圓角都由 CPU 處理锄码,且邊框清晰夺英,沒有黑邊,
3.2 缺點:不能處理子 View滋捶,在四角處的子 View 不會被「切」掉痛悯,畢竟是一個圓角背景造成的圓角假象,對子 View 沒有什么影響力重窟。
方案四 :使用遮罩層(推薦)
// 這個遮罩層不是上面提遮罩 layer载萌,是一張你想要保留的形狀的一張圖片,比如想要圓角圖片巡扇,可以讓設(shè)計師做一張這樣圖片:
// 中間透明扭仁,周圍是想要蓋住的形狀,最中看到的是中間留下來的形狀厅翔,這種做法沒有什么性能損耗乖坠,就是需要麻煩設(shè)計師做一張圖。
// 具體的做法見刀闷,也可以跑一下這個 demo 看看怎么對 UITableView 優(yōu)化的瓤帚。 https://github.com/johnil/VVeboTableViewDemo/blob/master/VVeboTableViewDemo/view/VVeboTableViewCell.m#L46
// 設(shè)計師需要做的圖:
五描姚、總結(jié):UIView圓角裁剪和加邊框方式匯總
5.1 在[離屏渲染優(yōu)化][http://www.reibang.com/p/ca51c9d3575b] (建議好好看看篇文章)中,seedante 對各種圓角方案也有總結(jié)對比戈次,最終得到這樣一個結(jié)果:
5.2 任何時候優(yōu)先考慮避免觸發(fā)離屏渲染轩勘,無法避免時優(yōu)化方案有兩種:
5.3 Rasterization:適用于靜態(tài)內(nèi)容的視圖,也就是內(nèi)部結(jié)構(gòu)和內(nèi)容不發(fā)生變化的視圖怯邪,對上面的所有效果而言绊寻,在實現(xiàn)成本以及性能上最均衡的。即使是動態(tài)變化的視圖悬秉,開啟 Rasterization 后能夠有效降低 GPU 的負(fù)荷澄步,不過在動態(tài)視圖里是否啟用還是看 Instruments 的數(shù)據(jù)。
5.4 規(guī)避離屏渲染和泌,用其他手法來模擬效果村缸,混合圖層是個性能最好、耗能最少的通用優(yōu)化方案武氓,尤其對于 rounded corer 和 mask梯皿。
5.5 總的來說,圓角方案需要根據(jù)情況具體選擇用哪種方式县恕。
UIView的layout機制解釋
// ios layout機制相關(guān)方法
- (CGSize)sizeThatFits:(CGSize)size
- (void)sizeToFit
——————-
- (void)layoutSubviews
- (void)layoutIfNeeded
- (void)setNeedsLayout
——————–
- (void)setNeedsDisplay
- (void)drawRect
/*
layoutSubviews在以下情況下會被調(diào)用:
1东羹、init初始化不會觸發(fā)layoutSubviews
但是是用initWithFrame 進行初始化時,當(dāng)rect的值不為CGRectZero時,也會觸發(fā)
2忠烛、addSubview會觸發(fā)layoutSubviews
3属提、設(shè)置view的Frame會觸發(fā)layoutSubviews,當(dāng)然前提是frame的值設(shè)置前后發(fā)生了變化
4美尸、滾動一個UIScrollView會觸發(fā)layoutSubviews
5冤议、旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件
6、改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件
在蘋果的官方文檔中強調(diào):
You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want.
layoutSubviews, 當(dāng)我們在某個類的內(nèi)部調(diào)整子視圖位置時师坎,需要調(diào)用求类。
反過來的意思就是說:如果你想要在外部設(shè)置subviews的位置,就不要重寫屹耐。
刷新子對象布局
-layoutSubviews方法:這個方法尸疆,默認(rèn)沒有做任何事情,需要子類進行重寫
-setNeedsLayout方法: 標(biāo)記為需要重新布局惶岭,異步調(diào)用layoutIfNeeded刷新布局寿弱,不立即刷新,但layoutSubviews一定會被調(diào)用
-layoutIfNeeded方法:如果按灶,有需要刷新的標(biāo)記症革,立即調(diào)用layoutSubviews進行布局(如果沒有標(biāo)記,不會調(diào)用layoutSubviews)
如果要立即刷新鸯旁,要先調(diào)用[view setNeedsLayout]噪矛,把標(biāo)記設(shè)為需要布局量蕊,然后馬上調(diào)用[view layoutIfNeeded],實現(xiàn)布局
在視圖第一次顯示之前艇挨,標(biāo)記總是“需要刷新”的残炮,可以直接調(diào)用[view layoutIfNeeded]
重繪
-drawRect:(CGRect)rect方法:重寫此方法,執(zhí)行重繪任務(wù)
-setNeedsDisplay方法:標(biāo)記為需要重繪缩滨,異步調(diào)用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:標(biāo)記為需要局部重繪
sizeToFit會自動調(diào)用sizeThatFits方法势就;
sizeToFit不應(yīng)該在子類中被重寫,應(yīng)該重寫sizeThatFits
sizeThatFits傳入的參數(shù)是receiver當(dāng)前的size脉漏,返回一個適合的size
sizeToFit可以被手動直接調(diào)用
sizeToFit和sizeThatFits方法都沒有遞歸苞冯,對subviews也不負(fù)責(zé),只負(fù)責(zé)自己
———————————-
layoutSubviews對subviews重新布局
layoutSubviews方法調(diào)用先于drawRect
setNeedsLayout在receiver標(biāo)上一個需要被重新布局的標(biāo)記侧巨,在系統(tǒng)runloop的下一個周期自動調(diào)用layoutSubviews
layoutIfNeeded方法如其名舅锄,UIKit會判斷該receiver是否需要layout.根據(jù)Apple官方文檔,layoutIfNeeded方法應(yīng)該是這樣的
layoutIfNeeded遍歷的不是superview鏈,應(yīng)該是subviews鏈
drawRect是對receiver的重繪司忱,能獲得context
setNeedDisplay在receiver標(biāo)上一個需要被重新繪圖的標(biāo)記皇忿,在下一個draw周期自動重繪,iphone device的刷新頻率是60hz烘贴,也就是1/60秒后重繪
*/