級別: ★★☆☆☆
標籤:「iOS佈局」「iOS frame」「iOS frame bounds」
做者: Xs·H
審校: QiShare團隊php
在 沐靈洛 線下分享iOS UIButton根據內容自動佈局時,有和前端同窗討論到iOS的經常使用佈局方式。討論過程十分熱鬧,不容易記錄,但做者認爲討論結果有必要記錄一下,但願能幫助到一些同窗。 做者將iOS經常使用佈局方式概括爲Frame、Autoresizing、Constraint、StackView和Masonry五種,並將逐一介紹。 本篇文章介紹
Frame
。前端
frame
是UIView
的屬性,用來描述UIView
及其子類所表示的視圖的位置(origin
)和大小(size
)。frame
是iOS
佈局中最基本、最經常使用和最容易被開發者接受的佈局方式。通常來講,能夠經過如下方式很方便地建立並顯示一個視圖,以下。git
- (void)viewDidLoad {
[super viewDidLoad];
_contentView = [[QiFrameContentView alloc] initWithFrame:self.view.bounds];
_contentView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:_contentView];
}
複製代碼
在上述代碼中,做者在viewDidLoad
中,將一個淺灰色的contentView
添加到了self.view
上,並將其frame
設置爲了self.view.bounds
。顯然,做者但願淺灰色的contentView
徹底蓋住self.view
(默認白色)。使用模擬器運行一下,初始效果如做者所願,但將模擬器旋轉方向後,淺灰色的contentView
沒有一塊兒旋轉,在右側漏出了一部分白色的self.view
,以下。github
上述現象實際上是frame特性的一種表現。在僅使用frame來佈局視圖時,視圖的位置和大小是被惟一肯定了的,不會跟隨父視圖的變化而變化,除非在某個時間點再次設置了frame。bash
做者但願contentView
能夠跟着self.view
一塊兒旋轉,始終保持徹底覆蓋的效果,因而作了以下修改。微信
- (void)viewDidLoad {
[super viewDidLoad];
_contentView = [[QiFrameContentView alloc] initWithFrame:CGRectZero];
_contentView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:_contentView];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
_contentView.frame = self.view.bounds;
}
複製代碼
爲實現想要的小夥,做者在viewWillLayoutSubviews
方法中從新設置了contentView
的frame
,並將viewDidLoad
中初始化contentView
時設置的frame
改成了CGRectZero
。由於在每一次self.view的frame變化後和self.view的子view發生變化前都會觸發viewWillLayoutSubviews方法。佈局
借鑑上面的原理,做者在contentView
上添加4
個subView
,實現4
等分的效果,以下圖。ui
實現上圖效果的代碼以下:spa
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_subView1 = [[UIView alloc] initWithFrame:CGRectZero];
_subView1.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:.6];
[self addSubview:_subView1];
_subView2 = [[UIView alloc] initWithFrame:CGRectZero];
_subView2.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:.6];
[self addSubview:_subView2];
_subView3 = [[UIView alloc] initWithFrame:CGRectZero];
_subView3.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:.6];
[self addSubview:_subView3];
_subView4 = [[UIView alloc] initWithFrame:CGRectZero];
_subView4.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:.6];
[self addSubview:_subView4];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat margin = 20.0;
CGFloat padding = 20.0;
CGFloat width = (self.bounds.size.width - margin * 2 - padding) / 2;
CGFloat height = (self.bounds.size.height - margin * 2 - padding) / 2;
_subView1.frame = CGRectMake(margin, margin, width, height);
_subView2.frame = CGRectMake(margin + width + padding, margin, width, height);
_subView3.frame = CGRectMake(margin, margin + height + padding, width, height);
_subView4.frame = CGRectMake(margin + width + padding, margin + height + padding, width, height);
/*
_subView4.qi_width = width;
_subView4.qi_height = height;
_subView4.qi_top = _subView3.qi_top;
_subView4.qi_left = _subView3.qi_right + padding;
*/
}
複製代碼
其中,經過打點可知contentView
中的layoutSubviews
方法與viewController
中的viewWillLayoutSubviews
方法成對觸發,而且layoutSubviews
晚於後者。3d
PS:bounds與frame有必定區別。
bounds只用來描述視圖的尺寸,就像一頁A4紙,不論把它放在桌子上仍是地板上,它的bounds都不發生變化。
frame除了可以描述視圖的尺寸外還能描述視圖的位置。再如A4紙,從桌子上挪到地板上,它的frame就發生變化了。
另外,爲了更方便、直觀地使用frame
佈局視圖,可使用相似上面代碼中註釋的代碼形式。具體的實現細節,能夠在QiLayoutDemo中查看。
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
iOS UIButton根據內容自動佈局
iOS 指定初始化方法
UIView中的hitTest方法
奇舞週刊