StackView

作者: VIC_LI | 来源:发表于2017-02-04 09:44 被阅读282次

    我的博客, 各位看官有时间赏光

    UIStackView

    UIStackView介绍

    随着autolayout的推广开来,更多的app开始使用自动布局的方式来构建自己的UI系统,autolayout配合storyBoard和一些第三方的框架,对于创建约束来说,已经十分方便,但是对于一些动态的线性布局的视图,我们需要手动添加的约束不仅非常多,而且如果我们需要插入或者移除其中的一些UI元素的时候,我们又要做大量的修改约束的工作,UIStackView正好可以解决这样的问题。

    UIStackViewiOS 9 中新增的一个控件,它继承于UIView,用来管理一行或一列视图的布局(堆叠视图的控制器类视图,所谓堆叠视图时一种平铺式的线性布局方式,不可重叠,布局方向也不可交错)。UIStackView新增了几个属性,这些属性就是子视图布局规则。一旦UIStackView的这些属性发生变化,它的arrangedSubviews就会按照规则重新排布。只要我们掌握这些规则,就可以管理视图布局了。如果能再稍加灵活运用,有时候我们甚至能轻松实现一些精妙布局。 UIStackView可以帮助开发者更加简单的使用layout而不必手动添加太多布局约束.

    属 性 作 用
    Axis 属性决定了 stack 的朝向,只有垂直或水平
    distribution 属性决定了其管理的视图在沿着其轴向上的布局
    Alignment 属性决定了其管理的视图在垂直于其轴向上的布局
    Spacing 属性决定了其管理的视图间的最小间隙
    layoutMarginsRelativeArrangement 属性决定了 stack 视图平铺其管理的视图时是否要参照它的布局边距
    baselineRelativeArrangement 属性决定了 stack 视图平铺其管理的视图时是否要参照它的布局边距

    ![Uploading 19_081418.png . . .]
    ](http:https://img.haomeiwen.com/i1129706/a300c78a3ddc0cdb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    UIStackViewDistribution

    axisspacingdistributionalignment是比较重要的4个属性,他们都能给布局带来明显的变化。axisspacing属性作用单一,通过属性解释或者通过视图简单观察我们就能理解他们的作用。distributionalignment这两个属性相对而言更具灵活性,也更具有难度,尤其是二者的结合使用。

    public enum UIStackViewDistribution : Int {
      case fill
      case fillEqually
      case fillProportionally
      case equalSpacing
      case equalCentering
    }
    
    public enum UIStackViewAlignment : Int {
      case fill   
      case leading
      public static var top: UIStackViewAlignment { get }
      case firstBaseline
      case center
      case trailing
      public static var bottom: UIStackViewAlignment { get }
      case lastBaseline 
    }
    
    • UIStackViewDistributionFill

    将arrangedSubviews填充满整个StackView,他们之间的间隙等于spacing大小

    如果减去所有的spacing,所有arrangedSubview的固有尺寸(intrinsicContentSize)之和不能填满StackView,那么就按照Hugging的优先级将其拉伸。反之,如果超出StackView的尺寸则按CompressionResistance的优先级压缩。如果优先级相同,就按排列顺序来拉伸或压缩。

    Hugging/CompressionResistance.png
    UIStackViewDistributionFill.png
    • UIStackViewDistributionFillEqually

    每个arrangedSubview沿axis方向的长度相等,等于StackView沿axis长度减去spacing之和除以arrangedSubviews个数。

    UIStackViewDistributionFillEqually.png
    • UIStackViewDistributionFillProportionally

      根据arrangedSubview的intrinsicContentSize,将StackView沿axis方向的长度减去spacing之和按比例分配给arrangedSubviews。

    UIStackViewDistributionFillProportionally.png
    • UIStackViewDistributionEqualSpacing

      先按arrangedSubviews的intrinsicContentSize布局,然后余下的空间均分为spacing

      如果spacing小于StackView设置的spacing,则按照CompressionResistance的优先级来压缩arrangedSubviews。

    UIStackViewDistributionEqualSpacing.png
    • UIStackViewDistributionEqualCentering

      令arrangedSubviews的中心点之间的距离相等,且spacing大于等于StackView设置的spacing(每两个arrangedSubview之间的spacing可能不相等)

      如果spacing小于StackView设置的spacing,则按照CompressionResistance的优先级来压缩arrangedSubviews。

    UIStackViewDistributionEqualCentering.png

    UIStackViewalignment

    • UIStackViewAlignmentFill

      在StackView轴向的垂直方向上拉伸所有子view来填充StackView

    UIStackViewAlignmentFill.png
    • UIStackViewAlignmentLeading

      用于stackview是垂直轴向时,所有子view靠左对齐

    UIStackViewAlignmentLeading.png
    • UIStackViewAlignmentTop

      用于stackview是水平轴向时,所有子view靠顶部对齐

    UIStackViewAlignmentTop.png
    • UIStackViewAlignmentCenter

      在StackView轴向的垂直方向上子视图以中线为基准对齐

    UIStackViewAlignmentCenter.png
    • UIStackViewAlignmentTrailing

      用于stackview是垂直轴向时,所有子view靠右对齐

    UIStackViewAlignmentTrailing.png
    • UIStackViewAlignmentBottom

      用于stackview是水平轴向时,所有子view靠底部对齐

    UIStackViewAlignmentBottom.png
    • UIStackViewAlignmentFirstBaseline

      用于stackview是水平轴向时,按照第一个子视图中文字的第一行对齐

    UIStackViewAlignmentFirstBaseline.png
    • UIStackViewAlignmentLastBaseline

      用于stackview是水平轴向时,按照最后一个子视图中文字的最后一行对齐

    UIStackViewAlignmentLastBaseline.png

    storyboard添加StackView

    • IB
    • 从对象库中拖拽UIStackView到storyboard中,然后往内部扔控件(UIView或其子类)就可以了。
    • 选择storyboard中的控件,可以用“command键 + 单击”进行多选,然后点击下方的stack按钮,这样选中的控件就会被放入一个StackView中。
    storyboard.png

    代码添加StackView

    • 创建UIStackView
        UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[forkingLabel, logoImageView, dogLabel]];
        stackView.translatesAutoresizingMaskIntoConstraints = NO;
        stackView.axis = UILayoutConstraintAxisHorizontal;
        stackView.distribution = UIStackViewDistributionFill;
        stackView.alignment = UIStackViewAlignmentCenter;
        stackView.spacing = 0;
       [self.view addSubview:stackView];
    
    • 动态的改变其中view的个数
    UIView * newView = [[UIView alloc]init];
    [stackView addArrangedSubview:newView];
    

    特别注意addArrangedSubviewaddSubview有很大的区别,使用前者是将视图添加进StackView的布局管理,后者只是简单的加在视图的层级上,并不接受StackView的布局管理。

    • 与之相对,我们可以使用下面的方法移除一个view
    UIView * view = [stackView arrangedSubviews].lastObject;
    [stackView removeArrangedSubview:view];
    

    StackView使用技巧

    • 嵌套 只要嵌套好UIStackView,就可以用很少的约束达到自动布局界面的目的

    使用StackView 嵌套 模仿同程首页布局

    嵌套_TC.png
    嵌套.png
    • 结合sizeClass 多屏幕适配
    查看SatckView的Attributes Inspector,我们会发现StackView的几个主要属性都是可以设置sizeclass模式的,
    这对我们的屏幕适配将会大有助益。再加上约束的sizeClass,灵活性可以想象。
    
    多屏幕适配.png
    • 因为StackView继承于UIView,因此在布局改变的时候,我们可以使用UIView层的动画 添加view的时候会有动画效果,移除的时候没有
    [stackView addArrangedSubview:newView];
    [UIView animateWithDuration:1 animations:^{
    [stackView layoutIfNeeded];
    }];
    
    
    stackView_gif.gif

    FDStackView

    UIStackView是在iOS9才推出的,最低支持的系统也是iOS9, FDStackView出现了,它就是为了解决UIStackView在低于iOS9的系统下无法使用的问题
    FDStackView之前也已经有了一些类似的开源项目,比如OAStackViewTZStackView,然而他们都不能满足我们的需求,局限性还是比较大的,比如不支持IB,某些功能还没有实现,类名需要使用非UIStackView,在我们看来这些对开发者来说都是不友好的,开发者需要的是一款功能完善,支持IB,使用时完全无感,在Xcode7上直接使用UIStackView即可,接下来的事情交给FDStackView就好,它负责将UIStackView在低于iOS9的系统上运行。

    需要注意如果使用IB的话,那么IBBuilds for属性需要设置为iOS 9.0 and later

    FDStackView.png
    • forkingdog开源小组的成员实现原理介绍
    Stay Hungry. Stay Foolish

    相关文章

      网友评论

        本文标题:StackView

        本文链接:https://www.haomeiwen.com/subject/uxvrbttx.html