iOS 常用布局方式之Autoresizing

級別: ★☆☆☆☆
標簽:「iOS布局」「iOS autoresizing」「autoresizingMask」
作者: Xs·H
審校: QiShare團隊

沐靈洛 線下分享iOS UIButton根據內容自動布局時,有和前端同學討論到iOS的常用布局方式。討論過程十分熱鬧,不容易記錄,但作者認為討論結果有必要記錄一下,希望能幫助到一些同學。
作者將iOS常用布局方式歸納為Frame、Autoresizing、Constraint、StackView和Masonry五種,并將逐一介紹。
本篇文章介紹Autoresizing。

autoresizing是iOS較早版本中出現的屏幕適配技術。當時,iOS設備機型少、app界面布局簡單,autoresizing可以較好地完成比如橫豎屏之類的視圖適配需求。在QiShare的項目中,autoresizing常與frame結合著使用來達到某些適配效果。比如,與上篇文章對比,用autoresizing可以更快速地實現淺灰色contentView完全覆蓋self.view并與之一起旋轉的效果,代碼如下。

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    _contentView = [[QiAutoresizingContentView alloc] initWithFrame:self.view.bounds];
    _contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _contentView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:_contentView];
}

在上述代碼中,contentView的autoresizingMask屬性起到了決定性作用。我們來認識下這個屬性。

@property(nonatomic) UIViewAutoresizing autoresizingMask;    // simple resize. default is UIViewAutoresizingNone
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

contentView的autoresizingMask屬性是一個位移枚舉UIViewAutoresizing。UIViewAutoresizing將視圖分為了LeftMargin(相對于父視圖的左邊距)、RightMargin(相對于父視圖的右邊距)、TopMargin(相對于父視圖的上邊距)、BottomMargin(相對于父視圖的下邊距)、Width(視圖自身的寬)和Height(視圖自身的高)6個屬性。在不設置autoresizingMask時默認使用UIViewAutoresizingNone賦值。當將autoresizingMask設置為某一個或多個值后,即設定該view的對應屬性可以隨著父視圖的變化而變化。

比如在上述代碼中,contentView的autoresizingMask被賦值為UIViewAutoresizingFlexibleWidth和UIViewAutoresizingFlexibleHeight,即設定contentView除了Width和Height可以隨著self.view的變化而變化外,其余4個屬性都被固定住了,所以能達到預期的效果,如下。

接下來,作者嘗試使用autoresizing實現上篇文章中4等分的效果,代碼如下。

- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    
    if (self) {
        
        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 = [[UIView alloc] initWithFrame:CGRectMake(margin, margin, width, height)];
        _subView1.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:.6];
        [self addSubview:_subView1];
        
        _subView2 = [[UIView alloc] initWithFrame:CGRectMake(margin + width + padding, margin, width, height)];
        _subView2.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:.6];
        [self addSubview:_subView2];
        
        _subView3 = [[UIView alloc] initWithFrame:CGRectMake(margin, margin + height + padding, width, height)];
        _subView3.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:.6];
        [self addSubview:_subView3];
        
        _subView4 = [[UIView alloc] initWithFrame:CGRectMake(margin + width + padding, margin + height + padding, width, height)];
        _subView4.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:.6];
        [self addSubview:_subView4];
        
        _subView1.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
        _subView2.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin;
        _subView3.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
        _subView4.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
    }
    
    return self;
}

實現的效果圖如下。

觀察上圖,在旋轉屏幕至橫屏后,4個subView之間的間距出了問題。這是因為UIViewAutoresizing枚舉中的6個值都是相對于父視圖的,不能實現同級視圖之間存在約束關系的場景需求。

要實現同級視圖之間的約束需求,閱讀下篇文章要講的Constraint會大有幫助。
另外,作者對contentView做了一個縮放動畫,可以更好地觀察視圖的變化情況。具體細節可以在QiLayoutDemo中查看。


推薦文章:
iOS UIButton根據內容自動布局
iOS 指定初始化方法
UIView中的hitTest方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容