概述


UIStackViewiOS 9中新增的API,类似于Android中的线性布局。UIStackView相当于一个容器,根据向UIStackView中添加视图的顺序,UIStackView会自动给这些视图添加约束,让这些视图根据内容,垂直或水平排列。由于UIStackView会自动给它里面的子视图添加约束,所以我们不必再为那些子视图添加约束,我们只要给UIStackView设置一些属性与其子视图的压缩或者拉伸的优先级就可以简单的实现视图布局。
如果稍微复杂的界面可以嵌套使用UIStackView,可以向UIStackView中添加UIStackView,本质上都是继承UIView


UIStackView介绍

介绍UIStackView中主要的API。图片来自于苹果官方文档


  • 初始化
- (instancetype)initWithArrangedSubviews:(NSArray<__kindof UIView *> *)views;
//初始化方法传入需要用UIStackView管理的存放子视图的数组,并按照数组中的顺序添加这些子视图。
  • 添加/移除子视图
- (void)addArrangedSubview:(UIView *)view;
//添加view到UIStackView对象上并且让UIStackView管理这个view布局

- (void)removeArrangedSubview:(UIView *)view;
//取消UIStackView的管理,但是这个view不从UIStackView上移除

- (void)insertArrangedSubview:(UIView *)view atIndex:(NSUInteger)stackIndex;
//UIStackView管理存放子视图的数组,按照顺序来布局,这个方法是向这个数组里指定位置添加view
  • UIStackView排列方式
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0, //子视图水平排列
    UILayoutConstraintAxisVertical = 1 //子视图垂直排列
};
@property(nonatomic) UILayoutConstraintAxis axis;
//这个属性是用来设置UIStackView中子视图的排列方式
  • 子视图分布样式
typedef NS_ENUM(NSInteger, UIStackViewDistribution) {
    UIStackViewDistributionFill = 0,
    UIStackViewDistributionFillEqually,
    UIStackViewDistributionFillProportionally,
    UIStackViewDistributionEqualSpacing,
    UIStackViewDistributionEqualCentering,
} NS_ENUM_AVAILABLE_IOS(9_0);

@property(nonatomic) UIStackViewDistribution distribution;
//UIStackView中子视图的分布样式

UIStackViewDistributionFill
根据UIStackView的排列方式,用子视图铺满填充指定的方向,如果指定的UIStackView是垂直排列那么UIStackView中的子视图将填充满UIStackView的高度。如果指定的UIStackView是水平排列那么UIStackView中的子视图将填充满UIStackView的宽度。下图就是填充UIStackView的宽度示例。由于每个视图是由UIStackView自动添加约束的,要进行铺满操作就对视图进行拉伸,指定某个视图拉伸,可以更改其压缩或者拉伸的优先级实现。

UIStackViewDistributionFillEqually
UIStackViewDistributionFillEqually保证铺满后如果是垂直排列所有的子视图高度相等,如果是水平排列所有的子视图宽度相等。

UIStackViewDistributionFillProportionally
根据每个子视图里面内容的尺寸来进行填充操作

UIStackViewDistributionEqualSpacing
排列视图,保证每个子视图之间的间距相等

UIStackViewDistributionEqualCentering
排列视图,保证每个子视图中心直接的间距相等

  • 子视图对齐方式
typedef NS_ENUM(NSInteger, UIStackViewAlignment) {
    UIStackViewAlignmentFill,
    UIStackViewAlignmentLeading,
    UIStackViewAlignmentTop = UIStackViewAlignmentLeading,
    UIStackViewAlignmentFirstBaseline,
    UIStackViewAlignmentCenter,
    UIStackViewAlignmentTrailing,
    UIStackViewAlignmentBottom = UIStackViewAlignmentTrailing,
    UIStackViewAlignmentLastBaseline, 
} NS_ENUM_AVAILABLE_IOS(9_0);
@property(nonatomic) UIStackViewAlignment alignment;
//设置`UIStackView`中子视图对齐的方式

UIStackViewAlignmentFill
UIStackView是垂直排列那么子视图的水平方向的左右边界与UIStackView上下边界对齐,如果是水平排列那么子视图的垂直方向的上下边界与UIStackView上下边界对齐。

UIStackViewAlignmentLeading
UIStackView是垂直排列时此值有效,让所有的子视图靠UIStackView左边界对齐。

UIStackViewAlignmentTop
UIStackView是水平排列时此值有效,让所有的子视图靠UIStackView上边界对齐。

UIStackViewAlignmentFirstBaseline
UIStackView是水平排列时此值有效,所有的子视图以每个视图中的第一行基准线对齐。

UIStackViewAlignmentCenter
所有的子视图中心与UIStackView的中心基准线对齐,如果UIStackView是水平排列那么所有子视图高度的中点与UIStackView高度中点对齐,如果如果UIStackView是垂直排列那么所有子视图宽度的中点与UIStackView宽度中点对齐。

UIStackViewAlignmentTrailing
UIStackView是垂直排列时此值有效,让所有的子视图靠UIStackView右边界对齐。

UIStackViewAlignmentBottom
UIStackView是水平排列时此值有效,让所有的子视图靠UIStackView下边界对齐。

UIStackViewAlignmentLastBaseline
UIStackView是水平排列时此值有效,所有的子视图以每个视图中的最后一行基准线对齐。

  • 子视图之间的间距
@property(nonatomic) CGFloat spacing
//每个子视图之间的间距,在某些布局的情况下spacing将作为最小的间距。

UIStackView使用

代码示例

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel *label1 = [[UILabel alloc] init];
    label1.text = @"label1";
    label1.textColor = [UIColor whiteColor];
    label1.backgroundColor = [UIColor orangeColor];
    UILabel *label2 = [[UILabel alloc] init];
    label2.text = @"label2";
    label2.textColor = [UIColor whiteColor];
    label2.backgroundColor = [UIColor grayColor];
    UILabel *label3 = [[UILabel alloc] init];
    label3.text = @"this is label3";
    label3.textColor = [UIColor whiteColor];
    label3.backgroundColor = [UIColor brownColor];
    // 初始化三个Label

    UIStackView *_stackView = [[UIStackView alloc] initWithArrangedSubviews:@[label1,label2,label3]];
    _stackView.axis = UILayoutConstraintAxisHorizontal;
    //_stackView中的子视图水平排列
    _stackView.distribution = UIStackViewDistributionFillProportionally;
    //按照内容填充水平方向_stackView的宽度。
    _stackView.alignment = UIStackViewAlignmentCenter;
    //所有的子视图高度的中点与_stackView的高度中点对齐
    _stackView.spacing = 5;
    //子视图之间的间距为5
    _stackView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self.view addSubview:_stackView];
    // Do any additional setup after loading the view, typically from a nib.
}

示例效果

如果更改UIStackView对象的某些属性

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel *label1 = [[UILabel alloc] init];
    label1.text = @"label1";
    label1.textColor = [UIColor whiteColor];
    label1.backgroundColor = [UIColor orangeColor];
    UILabel *label2 = [[UILabel alloc] init];
    label2.text = @"label2";
    label2.textColor = [UIColor whiteColor];
    label2.backgroundColor = [UIColor grayColor];

    UILabel *label3 = [[UILabel alloc] init];
    label3.text = @"this is label3";
    label3.textColor = [UIColor whiteColor];
    label3.backgroundColor = [UIColor brownColor];
    // 初始化三个Label

    UIStackView *_stackView = [[UIStackView alloc] initWithArrangedSubviews:@[label1,label2,label3]];
    _stackView.axis = UILayoutConstraintAxisHorizontal;
    //_stackView中的子视图水平排列
    _stackView.distribution = UIStackViewDistributionFill;
    //让所有子视图填充满UIStackView的宽度
    [label2 setContentHuggingPriority:100 forAxis:UILayoutConstraintAxisHorizontal];
    //设置label2的拉伸优先级priority值越低优先级越高,所以_stackView会优先拉伸label2。
    _stackView.alignment = UIStackViewAlignmentFill;
    //让子视图的上下边界与_stackView上下边界对齐
    _stackView.spacing = 5;
    //子视图之间的间距为5
    _stackView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self.view addSubview:_stackView];
}

示例效果


上面的示例只是简单的介绍了UIStackView的基本用法合理的嵌套使用可以实现很多复杂的界面布局。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐