UIStackView

UIStackView 堆栈视图是 iOS 9 引入的新特性,用于简化自动布局(Auto Layout),适用于水平或者垂直排布多个子视图的场景。

因为 UIStackView 适用于 StoryBoard 或者 NIB 情况下布局 UI 控件,因此参考了两个 Demo 学习使用:

记录总结了几个重点内容:

  1. UIStackView 的布局属性设置;
  2. 添加和移除子视图;
  3. 使用 Size Class 适配 Stack View;
  4. 学习使用Vertical Stack ViewHorizontal Stack View的相互嵌套。

一、UIStackView 布局属性

属性检查器设置
堆栈视图的两种布局方式
  • Axis:设置 Stack View 里面子视图的布局排列方式,水平方向布局(X 轴)还是垂直方向布局(Y 轴)。

    typedef enum UILayoutConstraintAxis : NSInteger {
        UILayoutConstraintAxisHorizontal = 0, // 水平方向布局
        UILayoutConstraintAxisVertical = 1    // 垂直方向布局
    } UILayoutConstraintAxis;
    
  • Alignment:设置垂直于布局方向(Axis 轴线)上的子视图的对齐方式。

    /** 
      UIStackViewAlignmentFill 会调整子视图的大小以填充 UIStackView 容器。
      而其他布局方式不会调整子视图大小,会使用子视图的固有内容大小(intrinsicContentSize)来布局子视图。
     */
    typedef enum UIStackViewAlignment : NSInteger {
        UIStackViewAlignmentFill,
        UIStackViewAlignmentLeading,
        UIStackViewAlignmentTop = UIStackViewAlignmentLeading,
        UIStackViewAlignmentFirstBaseline,
        UIStackViewAlignmentCenter,
        UIStackViewAlignmentTrailing,
        UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,
        UIStackViewAlignmentLastBaseline
    } UIStackViewAlignment;
    
  • Distribution:表示沿着布局方向(Axis 轴线)上的分布方式。

    typedef enum UIStackViewDistribution : NSInteger {
        UIStackViewDistributionFill = 0, // 填充,会调整子视图的大小以填充剩余空间。放大或缩小子视图时会使用子视图的压缩(compression resistance priority)、放大(hugging priority)优先级。
        UIStackViewDistributionFillEqually, // 均匀填充, 会调整子视图大小。
        UIStackViewDistributionFillProportionally, // 按比例分布,会调整子视图大小。
        UIStackViewDistributionEqualSpacing, // 分散对齐,子视图之间有间隙。
        UIStackViewDistributionEqualCentering // 中心对齐,
    } UIStackViewDistribution;
    
  • Spacing:表示子视图之间的最小距离。

  • baselineRelativeArrangement:布尔值,表示是否按照子视图的基线来调整垂直间距。

  • layoutMarginsRelativeArrangement:布尔值,表示子视图布局时,是相对于 UIStackView 的边界(bounds) 、还是相对于其边距(margins)。

二、添加和移除子视图

// ⚠️ 添加子视图时,如果子视图不在视图层次结构中,系统会自动将其作为 subviews 添加。
- (void)addArrangedSubview:(UIView *)view;

// ⚠️ 移除子视图时,Stack View 只会将其移出 arrangedSubviews 数组,移出 arrangedSubview 只是确保Stack View 不再管理其约束,而非从视图层次中删除。
- (void)removeArrangedSubview:(UIView *)view;

// 将子视图插入到 arrangedSubview 数组中
- (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;

Demo1 部分示例代码

#pragma mark - IBActions

// 点击按钮,添加一颗星星
- (IBAction)addStar:(id)sender {
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"star"]];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    
    // MARK: 通过调用 addArrangedSubview: 方法为 Stack View 添加并管理子视图
    [self.horizontalStackView addArrangedSubview:imageView];
    [UIView animateWithDuration:0.25 animations:^{
        /**
         由于 Stack View 自动为我们管理 Auto Layout constraints,
         我们只能调用 layoutIfNeeded 来实现动画。
         */
        [self.horizontalStackView layoutIfNeeded];
    }];
    
}

// 点击按钮,移除一颗星星
- (IBAction)removeStar:(id)sender {
    UIView *view = self.horizontalStackView.arrangedSubviews.lastObject;
    if (view) {
        // !!!: 调用 removeArrangedSubview: 只是告诉 Stack View 不再需要管理 subview 的约束。而 subview 会一直保持在视图层级结构中直到调用 removeFromSuperview 把它移除。
        [self.horizontalStackView removeArrangedSubview:view];
        // !!!: 调用 removeFromSuperview 是把 subview 从视图层级中移除
        [view removeFromSuperview];
        [UIView animateWithDuration:0.25 animations:^{
            [self.horizontalStackView layoutIfNeeded];
        }];
    }
}

三、使用 Size Class 适配 Stack View

使用 Size Class 可以让 iPhone 的 Stack View 在横屏下自适应,默认情况下是这样的

默认情况下,iPhone 旋转到水平状态时,图片还是竖直排布的。也就是说,无论 iPhone 是竖屏状态还是横屏状态,图片数组默认都是竖直排列的

默认iPhone横屏

但是如果我们想要在 iPhone 是横屏状态时,图片是水平排列的呢,就像下面这样,就需修改 Size Class 特性。

使用Size Class 后的iPhone横屏

首先需要看懂下面的一张图片:

Size Class

iPhone:

  • 竖屏(Portrait)显示时,size class 为:Width Compact, Height Regular(宽度压缩,高度正常)。竖屏状态时,我们需要让图片数组按照垂直方向排列,因此 wC hC 一栏设置为 Vertical
  • 横屏(Landscape)显示时,size class 为:Width Compact,Height Compact(宽度和高度都压缩)。横屏状态时,我们需要让图片数组按照水平方向排列,因此 wC hR 一栏设置为 Horizontal

具体设置项如下所示:

Size Class 设置

总结

UIStackView 可以极大简化用户界面的开发。使用 UIStackView 可以减少开发者为简单场景设置枯燥约束的步骤,可以把繁杂的工作交给 UIKit 管理。

你可能有一个问题,你是否应该使用 StackView?Apple 官方工程师建议开发人员应优先采用 StackView 来设计用户界面,然后仅在需要时才采用原始的自动布局方式,因此,开始使用 StackView 来设计你的用户界面吧,我想你会喜欢上它的。

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

推荐阅读更多精彩内容

  • UIStackView to resize/layout 自适应、适配、布局这几个关键词一直伴随着iOS开发,从以...
    萌新小透明阅读 2,105评论 1 1
  • UIStackView 类提供了一个高效的接口用于平铺一行或一列的视图组合。Stack视图使你依靠自动布局的能力,...
    Chivalrous阅读 788评论 1 2
  • 这是一篇挺老的文章,主要就是介绍在iOS9时推出的控件UIStackView。我发现网上的资料并不算多,而AppC...
    Liberalism阅读 11,092评论 2 26
  • Stack View提供横向和纵向的线性布局功能,管理着所有在它的 arrangedSubviews数组中的所有子...
    linatan阅读 1,505评论 1 4
  • UIStackView 这个控件,或许你没有接触过,但它的确很好用,特别是当你需要将一些lable、image、b...
    Jeavil_Tang阅读 775评论 0 6