1. 概念
苹果在iOS9中
UIKit
框架引入一个新的视图类UIStackView
:
UIStackView
视图 管理着所有在它的arrangedSubviews
属性 中的 视图的布局。- 这些视图根据它们在
arrangedSubviews
数组 中的顺序沿着UIStackView
视图 的 轴向排列。简而言之,
UIStackView
是一个ContainerView
,可以沿 横向或纵向 按照一定的规则 布局内部的子View
。
2. 详解
(1) 初始化
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
// 初始化方法,通过子视图数组初始化StackView
- (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views;
// 被排列子视图数组
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *arrangedSubviews;
(2) 属性
苹果开发文档给了一张图展示UIStackView
属性:
1> 属性axis
(轴向)
设置UIStackView
布局的方向:
@property(nonatomic) UILayoutConstraintAxis axis;
// 枚举
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
// 水平布局
UILayoutConstraintAxisHorizontal = 0,
// 垂直布局
UILayoutConstraintAxisVertical = 1
};
2> 属性distribution
(分布)
设置轴方向上 子视图的分布比例:
(如果axis
是水平方向,设置子视图的宽度;如果axis
是垂直方向,设置子视图的高度)
@property(nonatomic) UIStackViewDistribution distribution;
// 枚举
typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
// 填满
UIStackViewDistributionFill = 0,
// 子视图等比例填充
UIStackViewDistributionFillEqually,
// 原比例填充
UIStackViewDistributionFillProportionally,
// 以等距的空白填充子视图之间的空隙,如果填充超出StackView,则按照子视图顺序进行压缩
UIStackViewDistributionEqualSpacing,
// 依据子视图的中心点来平均分配布局,保持最小间距空白等距填充。超出区域则按照顺序压缩子视图
UIStackViewDistributionEqualCentering,
} API_AVAILABLE(ios(9.0));
3> 属性alignment
(对齐)
设置非轴方向上 子视图的对齐方式:
@property(nonatomic) UIStackViewAlignment alignment;
// 枚举
typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
// 填满,水平头尾对齐,垂直上下对齐
UIStackViewAlignmentFill,
// 水平头对齐
UIStackViewAlignmentLeading,
// 垂直上对齐
UIStackViewAlignmentTop = UIStackViewAlignmentLeading,
// 仅用于水平轴向,子视图与第一个控件基准线对齐
UIStackViewAlignmentFirstBaseline,
// 居中对齐
UIStackViewAlignmentCenter,
// 垂直尾部对齐
UIStackViewAlignmentTrailing,
// 水平底部对齐
UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,
// 仅用于水平轴向,子视图与最后一个控件基准线对齐
UIStackViewAlignmentLastBaseline,
} API_AVAILABLE(ios(9.0));
4> 属性spacing
(间隔)
设置轴方向上 子视图的间隔:
@property(nonatomic) CGFloat spacing;
5> 其他属性
// 布局时是否参照基准线,默认是NO
@property(nonatomic,getter=isBaselineRelativeArrangement) BOOL baselineRelativeArrangement;
// 设置布局时是否以控件的LayoutMargins为标准,默认为NO,是以控件的bounds为标准
@property(nonatomic,getter=isLayoutMarginsRelativeArrangement) BOOL layoutMarginsRelativeArrangement;
(3) 方法
// 添加子视图
- (void)addArrangedSubview:(UIView *)view;
// 移除子视图
- (void)removeArrangedSubview:(UIView *)view;
// 插入子视图
- (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;
注意:addArrangedSubview和insertArrangedSubview,会把子视图添加到arrangedSubviews数组的同时也添加到StackView上,但是removeArrangedSubview,只会把子视图从arrangedSubviews数组中移除,不会从subviews中移除,如果需要可调用removeFromSuperview。
当视图被加入、移出或插入 arrangedSubviews 数组时,或当一个被管理的子视图的 hidden 属性改变时,stack 视图都会自动更新它的布局。
3. iOS 11新增
(1) 新增属性
iOS 11新增两个属性:系统间隙、默认间隙
// 默认间隙
static const CGFloat UIStackViewSpacingUseDefault API_AVAILABLE(ios(11.0),tvos(11.0)) = FLT_MAX;
// 系统间隙
static const CGFloat UIStackViewSpacingUseSystem API_AVAILABLE(ios(11.0),tvos(11.0)) = FLT_MIN;
(2) 新增方法
iOS 11新增两个方法:
// 设置间隙
- (void)setCustomSpacing:(CGFloat)spacing afterView:(UIView *)arrangedSubview API_AVAILABLE(ios(11.0),tvos(11.0));
// 获得间隙值
- (CGFloat)customSpacingAfterView:(UIView *)arrangedSubview API_AVAILABLE(ios(11.0),tvos(11.0));