UIStackView学习分享, 纯代码实现

最近看叶孤城的书,里面提到了UIStackView,说起这种布局,也是很早就知道了,但是一直没有研究过,开发中也没有使用过,周末上网翻看一下了大家的文章,发现大多都是Storyboard讲解的,实际上使用代码或者Storyboard对于UIStackView区别不大,因为UIStackView本身的属性就很少,由于本人开发中从不使用Storyboard或者xib, 本篇demo就用纯代码完成吧, 关键是网上的一些布局给的示例也不是特别清楚,由于开发中也没有实际用过,本文内容仅限交流学习, 大家交流指正。

一,UIStackView是什么?
在iOS9中苹果在UIKit框架中引入了一个新的视图类UIStackView。UIStackView 类提供了一个高效的接口用于平铺一行或一列的视图组合。Stack视图管理着所有在它的 arrangedSubviews 属性中的视图的布局。这些视图根据它们在 arrangedSubviews 数组中的顺序沿着 Stack 视图的轴向排列。
简而言之,即UIStackView,就是一个ContainerView,可以沿横向或纵向按照一定的规则布局内部的子View。
为了避免太过无聊, 先放出demo中实现的一个效果, demo地址

效果

二,一个快速示例

下面用一个很简单的示例快速演示一下,


示例1

想一下要布局上图中的View,如果用Frame,或者autolayout的过程,都是比较复杂,masonry中有一种相对简单的方式, 可以看这篇文章masonry-等间距布局,以上方式都不演示了, 没什么可说的。

如果使用UIStackView, 如下为实现代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    containerView = [[UIStackView alloc] initWithFrame:CGRectMake(0, 100, ScreenWidth, 200)];
    containerView.axis = UILayoutConstraintAxisHorizontal;
    containerView.distribution = UIStackViewDistributionFillEqually;
    containerView.spacing = 10;
    containerView.alignment = UIStackViewAlignmentFill;
    
    for (NSInteger i = 0; i < 4; i++) {
        UIView *view = [[UIView alloc] init];
        view.backgroundColor = [UIColor colorWithRed:random()%256/255.0 green:random()%256/255.0 blue:random()%256/255.0 alpha:1];
        [containerView addArrangedSubview:view];
    }
    
    [self.view addSubview:containerView];
}

以上就是所有代码, 是不是看起来异常简单, 前面说过了StackView其实就是一个容器View,可以管理内部子控件的布局, 那么看一下代码, init不用说了, for循环创建子控件不用说了(addArrangedSubview:view见下文), addSubViews也不用说, 那么久只剩下了四行代码, 这四个也就是UIStackView全部四个属性

[containerView addArrangedSubview:view]相关介绍:
UIStackView使用arrangedSubviews数组来管理子视图。
需要注意的是这个数组是一个readonly的属性,我们需要调用方法对arrangedSubviews数组进行操作。
初始化数组:
- (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views;
添加子视图: 
- (void)addArrangedSubview:(UIView *)view;
移除子视图:
- (void)removeArrangedSubview:(UIView *)view;
根据下标插入视图:
- (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;

注意: addArrangedSubview 和 insertArrangedSubview, 会把子控件加到arrangedSubviews数组的同时添加到StackView上, 
      但是removeArrangedSubview, 只会把子控件从arrangedSubviews数组中移除,
      不会从subviews中移除,如果需要可调用removeFromSuperview

三,具体讲解StackView的属性

stackView属性示例图

1, axis:子控件的布局方向,水平或垂直, 这个不用过多解释了
2, spacing:子控件之间的最小间距,之所以说是最小间距,因为stackView会根据一定的规则对内部空间布局,有的时候不能满足所有要求,比如stackView 本身宽度100,内部两个控件,宽度都为50,50+50+10就超过了本身宽度, 这时会压缩其中一个子控件的宽度来满足最小间距。
3, distribution:子控件依据何种规则布局, 这个比较抽象, 看示例理解的快一点,以下示例均使用UILabel演示, 原因见插播

插播:先了解一下什么是Intrinsic Content Size(固有尺寸),
因为UIStackView对子控件的布局是建立在Autolayout基础之上的,
会涉及到Intrinsic Content Size
想一下当为一个Label创建约束时,是不是经常只指定上边距和左边距,
相信原因大家都知道,label内部的文字自会撑开宽高, 
这个根据内容自己撑开的宽高就是Intrinsic Content Size。
怎样给一个UIView设置Intrinsic Content Size 或者改变label的Intrinsic Content Size?
继承然后重写
- (CGSize)intrinsicContentSize
{
    CGSize originalSize = [super intrinsicContentSize];
    CGSize size = CGSizeMake(originalSize.width+20, originalSize.height+20);
    return size;
}

UIStackViewDistribution是个枚举值, 各个值如下, 配有示例图, 看不懂就只能自求多福了:
UIStackViewDistributionFill :它就是将 arrangedSubviews 填充满整个 StackView ,如果设置了spacing,那么这些 arrangedSubviews 之间的间距就是spacing。如果减去所有的spacing,所有的 arrangedSubview 的固有尺寸( intrinsicContentSize )不能填满或者超出 StackView 的尺寸,那就会按照 Hugging 或者 CompressionResistance 的优先级来拉伸或压缩一些 arrangedSubview 。如果出现优先级相同的情况,就按排列顺序来拉伸或压缩。

UIStackViewDistributionFillEqually :这种就是 StackView 的尺寸减去所有的spacing之后均分给 arrangedSubviews ,每个 arrangedSubview 的尺寸是相同的。

UIStackViewDistributionFillProportionally :这种跟FillEqually差不多,只不过这个不是讲尺寸均分给 arrangedSubviews ,而是根据 arrangedSubviews 的 intrinsicContentSize 按比例分配。

UIStackViewDistributionEqualSpacing :这种是使 arrangedSubview 之间的spacing相等,但是这个spacing是有可能大于 StackView 所设置的spacing,但是绝对不会小于。这个类型的布局可以这样理解,先按所有的 arrangedSubview 的 intrinsicContentSize 布局,然后余下的空间均分为spacing,如果大约 StackView 设置的spacing那这样就OK了,如果小于就按照 StackView 设置的spacing,然后按照 CompressionResistance 的优先级来压缩一个 arrangedSubview 。

UIStackViewDistributionEqualCentering :这种是使 arrangedSubview 的中心点之间的距离相等,这样没两个 arrangedSubview 之间的spacing就有可能不是相等的,但是这个spacing仍然是大于等于 StackView 设置的spacing的,不会是小于。这个类型布局仍然是如果 StackView 有多余的空间会均分给 arrangedSubviews 之间的spacing,如果空间不够那就按照 CompressionResistance 的优先级压缩 arrangedSubview 。

4,alignment 子控件对其方式,类似UIlabel的textAlignment, 可以做一个类比, UILabel对应UIStackView, label的内容对应StackView的子控件。

UIStackViewDistribution是个枚举值, 各个值如下:

UIStackViewAlignmentFill, 默认方式, 如果子控件水平布局, 则指子控件的垂直方向填充满stackView. 反之亦然

UIStackViewAlignmentLeading, 如果子控件竖直布局, 则指子控件左边对齐stackView左边. 反之亦然, 即 UIStackViewAlignmentTop = UIStackViewAlignmentLeading。

UIStackViewAlignmentTop = UIStackViewAlignmentLeading,

UIStackViewAlignmentFirstBaseline, 根据上方基线布局所有子视图的y值(适用于Horizontal模式), 这种模式没搞懂, 有知道怎么回事的求教了

UIStackViewAlignmentLastBaseline, 根据下方基线布局所有子视图的y值(适用于Horizontal模式)

UIStackViewAlignmentCenter, 中心对齐

UIStackViewAlignmentTrailing, 如果子控件竖直布局, 则指子控件左边对齐stackView右边. 反之亦然, 即UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing

UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,

四, 另一个有意思一点的示例, 同时演示stackView的嵌套

即文章开头放出的动态图,
这个效果使用了两个StackView, 一个horizontalView, 一个verticalView,horizontalView即示例下方水平排布的View, 这个horizontalView也添加到verticalView的arrangedSubviews数组中, 具体实现看代码吧, 不多说了
github地址 : UIStackVIewDemo

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

推荐阅读更多精彩内容

  • 目录 0、前言 一、Auto Layout前世今生 二、Auto Layout基础知识 1.Auto Layout...
    浮游lb阅读 24,402评论 3 89
  • 前言 首先,我们通过下面这张图片引出今天的主角 大家看到了什么,是爱吗?不,这不是爱,不是爱,是满满的‘愁绪’?😂...
    一念之见阅读 2,191评论 0 2
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 翻译自“Auto Layout Guide”。 1 入门 1.1 理解自动布局 自动布局根据视图层级结构中视图上的...
    lakerszhy阅读 3,569评论 3 26
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,799评论 25 707