0%

iOS 编程:UIStackView

GitHub 开源框架: OAStackView

UIStackView 是用于布局按行或者按列排布的视图集合的精简接口。

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

Demo 1

  • 【原文】iOS 9: Getting Started with UIStackView
  • 【译文】iOS 9: UIStackView 入门

Demo 2

  • 【原文】An Introduction to Stack Views in iOS 9 and Xcode 7
  • 【译文】IOS9 Xcode7 下的布局神器 Stack Views

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

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

一、UIStackView 布局属性

属性检查器设置

属性设置示意图

  • Axis 表示堆栈视图的布局方向,水平方向布局(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 示例

// 添加星星
- (IBAction)addStarButtonDidClicked:(id)sender {
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"star"]];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    [self.horizontalStarkView addArrangedSubview:imageView];
    [UIView animateWithDuration:0.25 animations:^{
        [self.horizontalStarkView layoutIfNeeded];
    }];
}

// 移除星星
- (IBAction)removeStarButtonDidClicked:(id)sender {
    UIView *view = self.horizontalStarkView.arrangedSubviews.lastObject;
    if (view) {
        [self.horizontalStarkView removeArrangedSubview:view];
        [view removeFromSuperview];
        [UIView animateWithDuration:0.25 animations:^{
            [self.horizontalStarkView layoutIfNeeded];
        }];
    }
}

Demo1.gif

三、使用 Size Class 适配 Stack View

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

默认情况下,iPhone 旋转到水平状态时,图片还是竖直排布的。

默认iPhone横屏

但是如果我们想要在水平状态时,图片是水平排布的呢,就像下面这样,就需要用到 Size Class。

使用Size Class 后的iPhone横屏

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

Size Class

iPhone:

  • 竖屏(Portrait)显示时,size class 为:Width Compact,Height Regular. 此时需要垂直排列,设置为 Vertical;
  • 横屏(Landscape)显示时,size class 为:Width Compact,Height Compact. 此时需要水平排列,设置为 Horizontal;

设置:

Size Class 设置

欢迎关注我的其它发布渠道