iOS9新特性——堆疊視圖UIStackView

iOS9新特性——堆疊視圖UIStackView

1、引言

        隨着autolayout的推廣開來,更多的app開始使用自動佈局的方式來構建本身的UI系統,autolayout配合storyBoard和一些第三方的框架,對於建立約束來講,已經十分方便,可是對於一些動態的線性佈局的視圖,咱們須要手動添加的約束不只很是多,並且若是咱們須要插入或者移除其中的一些UI元素的時候,咱們又要作大量的修改約束的工做,UIStackView正好能夠解決這樣的問題。數組

2、在storyBoard上初識StackView

        UIStackView是一個管理一組堆疊視圖的控制器類視圖,所謂堆疊視圖時一種平鋪式的線性佈局方式,不可重疊,佈局方向也不可交錯,若是你作過watchOS的開發,你會發現,其實StackView與watchOS中的group十分能類似。app

例如,咱們若是須要一個以下效果的佈局,在屏幕的中間擺放幾個大小一致的色塊,不管屏幕朝向如何,其位置都不會變化,而且能夠向其中添加和移除色塊的數量:框架

       

首先,咱們在ViewController中拉入一個stackView:dom

將一些屬性設置以下:佈局

Axis是設置佈局的方向,有水平和垂直兩種方式,一個StackView只能選擇一種佈局模式。學習

Alignment是選擇其管理視圖的對齊模式,咱們這裏選擇充滿。動畫

Distribution是設置其管理視圖的排列方式,咱們選擇等寬充滿。atom

Spacing是設置視圖之間的間距,設置爲10.spa

以後有一點須要注意,stackView用於佈局其內部管理的視圖,對於它自己,咱們還須要添加一些約束,將它約束在屏幕的中間。code

咱們向其中拖入任意數量的view,設置不一樣的顏色,就實現了咱們想要的效果,而且能夠隨意動態刪除和添加其中的view數量,不須要改變約束。

3、從代碼學習UIStackView

        經過代碼建立一個UIStackView也很是簡單,首先,咱們先經過代碼實現上面的效果:

 NSMutableArray * array = [[NSMutableArray alloc]init];
    for (int i =0 ; i<5; i++) {
        UIView * view = [[UIView alloc]init];
        view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
        [array addObject:view];
    }
    UIStackView * stackView = [[UIStackView alloc]initWithArrangedSubviews:array];
    [self.view addSubview:stackView];
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.centerY.equalTo(self.view.mas_centerY);
        make.leading.equalTo(self.view.mas_leading).offset(20);
        make.trailing.equalTo(self.view.mas_trailing).offset(-20);
        make.size.height.equalTo(@100);
    }];
    stackView.axis = UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFillEqually;
    stackView.alignment = UIStackViewAlignmentFill;

效果圖以下:

   

咱們的佈局沒有問題,而且能夠動態的改變其中view的個數,使用以下方法添加一個view:

    UIView * newView = [[UIView alloc]init];
    newView.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
    [stackView addArrangedSubview:newView];

與之相對,咱們可使用下面的方法移除一個view:

    UIView * view = [stackView arrangedSubviews].lastObject;
    [stackView removeArrangedSubview:view];

特別注意:addArrangedSubview和addSubview有很大的區別,使用前者是將試圖添加進StackView的佈局管理,後者只是簡單的加在試圖的層級上,並不接受StackView的佈局管理。

技巧:由於StackView繼承於UIView,所以在佈局改變的時候,咱們可使用UIView層的動畫,以下:

        //在添加view的時候會有動畫效果,移除的時候沒有
        [stackView addArrangedSubview:newView];
        [UIView animateWithDuration:1 animations:^{
            [stackView layoutIfNeeded];
        }];

4、再來深刻理解下UIStackView

        經過上面的介紹,咱們已經基本瞭解了StackView的使用和特色,下面咱們再來仔細介紹一下與其相關的屬性和方法的使用,使咱們可以更加駕輕就熟。

有關被管理視圖的添加與移除:

//初始化方法,經過數組傳入被管理的視圖
- (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views; 
//獲取被管理的全部視圖
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *arrangedSubviews;
//添加一個視圖進行管理
- (void)addArrangedSubview:(UIView *)view;
//移除一個被管理的視圖
- (void)removeArrangedSubview:(UIView *)view;
//在指定位置插入一個被管理的視圖
- (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;

與StackView佈局設置相關:

1.佈局模式:

@property(nonatomic) UILayoutConstraintAxis axis;

上面這個屬性用於設置佈局的模型,枚舉以下:

//stackView只有兩種佈局模式 水平和豎直
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    //水平佈局
    UILayoutConstraintAxisHorizontal = 0,
    //豎直佈局
    UILayoutConstraintAxisVertical = 1
};

2.對齊模式: 

@property(nonatomic) UIStackViewAlignment alignment;

這個屬性用於設置控件的對其模式,枚舉以下:

typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
   //水平佈局時爲高度充滿,豎直佈局時爲寬度充滿
    UIStackViewAlignmentFill,
    //前邊對其
    UIStackViewAlignmentLeading,
    //頂部對其
    UIStackViewAlignmentTop = UIStackViewAlignmentLeading,
    //第一個控件文字的基線對其 水平佈局有效
    UIStackViewAlignmentFirstBaseline, 
    //中心對其
    UIStackViewAlignmentCenter,
    //後邊對其
    UIStackViewAlignmentTrailing,
    //底部對其
    UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,
    //基線對其,水平佈局有效
    UIStackViewAlignmentLastBaseline, 
} NS_ENUM_AVAILABLE_IOS(9_0);

在上面的例子中,咱們設置了對其方式爲充滿,這樣的話,咱們就不須要再作過多控件尺寸的約束,若是咱們被管理的控件高度或者寬度不一,咱們能夠設置中心對其,這樣的話,咱們還須要爲每一個控件添加一個寬度或者高度的約束,以下:

    NSMutableArray * array = [[NSMutableArray alloc]init];
    for (int i =0 ; i<5; i++) {
        UIView * view = [[UIView alloc]init];
        view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
        float height = arc4random()%90+10;
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo([NSNumber numberWithFloat:height]);
        }];
        [array addObject:view];
    }
    stackView = [[UIStackView alloc]initWithArrangedSubviews:array];
    [self.view addSubview:stackView];
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.view.mas_centerX);
        make.centerY.equalTo(self.view.mas_centerY);
        make.leading.equalTo(self.view.mas_leading).offset(20);
        make.trailing.equalTo(self.view.mas_trailing).offset(-20);
        make.size.height.equalTo(@100);
    }];
    stackView.axis = UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFillEqually;
    stackView.alignment = UIStackViewAlignmentCenter;

效果以下:

 

  

這樣,良莠不齊的控件佈局咱們也能夠輕鬆完成。

3.排列方式

@property(nonatomic) UIStackViewDistribution distribution;

排列方式的枚舉以下:

typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
    //充滿,當只有一個控件時可使用
    UIStackViewDistributionFill = 0,
    //平分充滿,每一個控件佔據相同尺寸排列充滿
    UIStackViewDistributionFillEqually,
    //會優先按照約束的尺寸進行排列,若是沒有充滿,會拉伸最後一個排列的控件充滿
    UIStackViewDistributionFillProportionally,
    //等間距排列
    UIStackViewDistributionEqualSpacing,
    //中心距離相等
    UIStackViewDistributionEqualCentering,
} NS_ENUM_AVAILABLE_IOS(9_0);

注意,除了咱們選擇fill屬性時不需約束控件視圖的尺寸,其餘都須要進行約束,例如若是咱們選擇等間距,我把改爲以下代碼:

     [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo([NSNumber numberWithFloat:height]);
            make.width.equalTo(@50);
            
        }];
     stackView.distribution = UIStackViewDistributionEqualSpacing;

效果以下:

 

4.其餘

//設置最小間距
@property(nonatomic) CGFloat spacing;
//設置佈局時是否參照基線
@property(nonatomic,getter=isBaselineRelativeArrangement) BOOL baselineRelativeArrangement;
//設置佈局時是否以控件的LayoutMargins爲標準,默認爲NO,是以控件的bounds爲標準
@property(nonatomic,getter=isLayoutMarginsRelativeArrangement) BOOL layoutMarginsRelativeArrangement;

5、UIStackView的嵌套

        一個StackView不容許咱們進行水平和豎直的交叉佈局,可是咱們能夠經過嵌套的方式來實現複雜的佈局效果,好比咱們實現一個相似電影表標籤,可使用水平佈局的StackView中嵌套一個豎直佈局的StackView:

十分輕鬆就能夠實現以下的效果:

 

  

看到了吧,經過StackView,咱們沒有添加過多的約束,使咱們佈局起來更加輕鬆了。若是你經常使用storyBoard進行開發,還有一個小技巧能夠方便的將兩個控件整合到一個StackView中,按住command,選中兩個控件,以後點擊右下角的以下圖標,系統會自動幫咱們生成一個StackView,將選中的兩個控件整合進去,很酷吧!


 


 

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索