UIStackView简单理解和使用

一、UIStackView简介

UIStackView是iOS9中新增的API,类似于Android中的线性布局。UIStackView提供了一个高效的接口用于平铺一行或一列的视图组合。对于嵌入到StackView的视图,你不用再添加自动布局的约束了。Stack View管理这些子视图的布局,并帮你自动布局约束。也就是说,这些子视图能够适应不同的屏幕尺寸。此外,你可以嵌入一个stack View到另一个stack view中来创建更为复杂的用户界面。不要误解我的意思,这并不意味着你就不需要处理自动布局了。你仍旧要定义一些布局约束来约束stack view。它只是帮你节约了为每个UI元素创建约束的时间,同时它更容易的从布局中添加/删除一个视图。

     UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.frame = CGRectMake(100, 100, 200, 50);
    stackView.backgroundColor = [UIColor redColor];
    UILabel *lable = [[UILabel alloc] init];
    lable.text = @“测试”;
    lable.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
    [stackView addArrangedSubview:lable];
  • 1、 UIStackView是UIView的子类,但backgroundColor 设置是无效的
  • 2、UIStackView是通过它的 arrangedSubviews属性列表来管理view的, 而通过- (void)addArrangedSubview:(UIView *)view就可以将view添加到arrangedSubviews中
  • 3、 stack view 用自动布局的方式来确定其子view的大小和位置。
  • 4、在水平方向上,第一个view的左边缘和stack view的左边缘是对齐的,最后一个view的右边缘和stack view的右边
    边缘是对齐的,


    截屏2020-08-20 上午10.22.14.png
截屏2020-08-20 上午10.23.50.png

如果你再去这样给子view设置左边的约束,自然是无效的

   [lable mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(stackView).offset(20);
    }];

控制台也会打印这样约束冲突的错误
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
因此需要注意的是,UIStackview内部也是通过约束来实现的,因此,必须提供足够的且正确的约束才能使用好它。

二、axis

@property(nonatomic) UILayoutConstraintAxis axis;
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0,
    UILayoutConstraintAxisVertical = 1
};

管理子view的布局方向,属性值决定了子view的排布是按水平方向依次排布,还是沿着竖直方向依次排布。默认是UILayoutConstraintAxisHorizontal

 stackView.axis  =  UILayoutConstraintAxisHorizontal;
截屏2020-08-20 下午1.50.54.png
  stackView.axis  =  UILayoutConstraintAxisVertical;
截屏2020-08-20 下午1.51.38.png

三、distribution

property(nonatomic) UIStackViewDistribution distribution;
typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
    UIStackViewDistributionFill = 0,
    UIStackViewDistributionFillEqually,
    UIStackViewDistributionFillProportionally,
    UIStackViewDistributionEqualSpacing,
    UIStackViewDistributionEqualCentering,
} ;

决定着在轴线方向上是怎么样布局的,默认值是UIStackViewDistributionFill

  • 1、UIStackViewDistributionFill:子view填满主轴方向StackView空间。
  • 2、 UIStackViewDistributionFillEqually:使所有子视图在轴方向上等宽或等高
  • 3、UIStackViewDistributionFillProportionally:根据原先子视图的比例来拉伸或压缩子视图的宽或高
  • 4、UIStackViewDistributionEqualSpacing:所有子视图中间的间隔保持一致
  • 5、UIStackViewDistributionEqualCentering: 所有子视图的中心之间的距离保持一致

3.1、UIStackViewDistributionFill

1、stackView 大小约束确定

    UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFill;
    stackView.frame = CGRectMake(30, 100, 300, 300);
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
           if (i<3) {
             [view mas_makeConstraints:^(MASConstraintMaker *make) {
                    make.width.equalTo(@90);
            }];
        }
    }
   
  • stackView大小约束确定:通过指定子元素的大小约束或者固有大小来布局子元素,当所有子元素超出stackView或者没有充满stackView,会自动根据约束的优先级对某一个子view拉伸或者压缩;当约束优先级不能确定时,就按照排布的顺序,对最后一个view拉伸或者压缩;

2、stackView 大小不确定


    UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFill;
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(10);
    }];
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
             [view mas_makeConstraints:^(MASConstraintMaker *make) {
                 make.width.height.equalTo(@90);
          }];

stackView 大小不确定:所有的子元素指定大小约束,会自动根据子元素调整stackView的大小。

3.2、 UIStackViewDistributionFillEqually

1、stackView 大小约束确定

   UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFillEqually;
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(10);
        make.height.equalTo(@200);
        make.width.equalTo(@300);
    }];
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
    }

2、stackView 大小约束不确定

    UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionFillEqually;
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(10);
    }];
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.width.equalTo(@60);
            make.height.equalTo(@300);
        }];
    }

3、 UIStackViewDistributionEqualSpacing

1、stackView 大小约束确定

    UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionEqualSpacing;
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(10);
        make.width.equalTo(@300);
        make.height.equalTo(@100);
    }];
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.width.equalTo(@30);
        }];
    }

2、stackView 大小约束不确定

   UIStackView *stackView = [[UIStackView alloc] init];
    [self.view addSubview:stackView];
    stackView.spacing = 20;
    stackView.axis  =  UILayoutConstraintAxisHorizontal;
    stackView.distribution = UIStackViewDistributionEqualSpacing;
    [stackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(10);
        make.height.equalTo(@100);
    }];
    for (int i=0; i<4; i++) {
        UIView *view  =[[UIView alloc]init];
        [stackView addArrangedSubview:view];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.width.equalTo(@30);
        }];
    }
   

4、 spacing

  • 1、Fill distributions( UIStackViewDistributionFill 、 UIStackViewDistributionFillEqually、 UIStackViewDistributionFillProportionally): spacing确定了子view的严格间距
  • 2、other(UIStackViewDistributionEqualSpacing、 UIStackViewDistributionEqualCentering):spacing作为了 最小间距,可能子view之间的间距会更大一些。

四、alignment

@property(nonatomic) UIStackViewAlignment alignment;
typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
    UIStackViewAlignmentFill,子视图填充StackView
    UIStackViewAlignmentLeading,子视图左对齐(axis为垂直方向而言)
    UIStackViewAlignmentTop = UIStackViewAlignmentLeading,子视图顶部对齐(axis为水平方向而言)
    UIStackViewAlignmentFirstBaseline, 按照第一个子视图的文字的第一行对齐,同时保证高度最大的子视图底部对齐(只在axis为水平方向有效)
  
    UIStackViewAlignmentCenter,子视图居中对齐
   
    UIStackViewAlignmentTrailing,子视图右对齐(axis为垂直方向而言)

    UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,子视图底部对齐(axis为水平方向而言)
    UIStackViewAlignmentLastBaseline, 按照最后一个子视图的文字的最后一行对齐,同时保证高度最大的子视图顶部对齐(只在axis为水平方向有效)
} ;

决定了垂直轴方向的布局


截屏2020-08-20 下午5.03.34.png
    UIStackView *containerView = [[UIStackView alloc] init];
    containerView.axis = UILayoutConstraintAxisHorizontal;
    containerView.alignment =   UIStackViewAlignmentTop ;
    containerView.spacing = 10;
    NSMutableString *testString =[[NSMutableString alloc]init];
    for (int i=0; i<5; i++) {
        UILabel *lable = [[UILabel alloc] init];
        lable.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
        [containerView addArrangedSubview:lable];
        NSString *str = [NSString stringWithFormat:@"%d",I];
        [testString appendString:str];
        lable.text = testString;
    }
    [self.view addSubview:containerView];
    [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.offset(100);
        make.centerX.equalTo(self.view);
        make.height.equalTo(@100);
    }];
截屏2020-08-20 下午5.24.44.png

五、实战应用

一、封装一个图文位置上、下、左、右调整的按钮

//www.greatytc.com/p/72882fded55a

二、UIScrollView+UIStackView

//www.greatytc.com/p/fea8f927beb6

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容