iOS 經常使用佈局方式之Frame

級別: ★★☆☆☆
標籤:「iOS佈局」「iOS frame」「iOS frame bounds」
做者: Xs·H
審校: QiShare團隊php

沐靈洛 線下分享iOS UIButton根據內容自動佈局時,有和前端同窗討論到iOS的經常使用佈局方式。討論過程十分熱鬧,不容易記錄,但做者認爲討論結果有必要記錄一下,但願能幫助到一些同窗。 做者將iOS經常使用佈局方式概括爲Frame、Autoresizing、Constraint、StackView和Masonry五種,並將逐一介紹。 本篇文章介紹 Frame前端

frameUIView的屬性,用來描述UIView及其子類所表示的視圖的位置(origin)和大小(size)。frameiOS佈局中最基本、最經常使用和最容易被開發者接受的佈局方式。通常來講,能夠經過如下方式很方便地建立並顯示一個視圖,以下。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方法中從新設置了contentViewframe,並將viewDidLoad中初始化contentView時設置的frame改成了CGRectZero由於在每一次self.view的frame變化後和self.view的子view發生變化前都會觸發viewWillLayoutSubviews方法。佈局

借鑑上面的原理,做者在contentView上添加4subView,實現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方法
奇舞週刊

相關文章
相關標籤/搜索