UILayoutGuide

NSLayoutAnchor

在 iOS 9.0 之后,UIView 中新增了一个 UIViewLayoutConstraintCreation 分类,该分类声明了一些 NSLayoutAnchor 属性,用来简化视图约束的创建。

NSLayoutAnchor 虽然给出了 NSLayoutXAxisAnchorNSLayoutYAxisAnchorNSLayoutDimension 三个子类,分别用来描述横向、纵向和长宽的相关信息,但是并没有声明任何属性或初始化方法。

从 UIView 的 UIViewLayoutConstraintCreation 分类中属性的只读特性来看,其是由框架内部创建,并且完全是对开发者透明的,使用的形式如下:

[myView.topAnchor constraintEqualToAnchor:otherView.topAnchor constant:10];

那么,NSLayoutAnchor 更像是对 NSLayoutAttribute 的封装。如果根据约束的核心公式推断,该类中也定然保存着相关联的视图。

UILayoutGuide

为了适配不同的机型,规避状态栏或导航栏带来的视图布局影响,可以使用 UIViewController 分类 UILayoutSupport 中的 topLayoutGuidebottomLayoutGuide 属性。不过 iOS 11.0 之后,使用 UIView 中的 safeAreaLayoutGuide 属性更加方便。
这个属性是 UILayoutGuide 类,该类在 iOS 9.0 就生效了。巧的是,其也声明了同 UIViewLayoutConstraintCreation 分类中相同的属性,且是只读的。

@property(nonatomic,readonly,strong) NSLayoutXAxisAnchor *leadingAnchor;
//...
@property(nonatomic,readonly,strong) NSLayoutYAxisAnchor *centerYAnchor;

实际上,从 safeAreaLayoutGuide 属性就可以知道,UILayoutGuide 实例对象是可以用来创建约束的,其定义了布局中的一个长方形区域,同视图类似,但是他们并不会显示在视图层级中,也不会响应相关的事件。

- (void)btnClick {
    
    NSMutableArray *btns = [NSMutableArray arrayWithCapacity:2];
    for (int i=0;i<2;i++) {
        UIButton *btn = [[UIButton alloc]init];
        btn.backgroundColor = UIColor.redColor;
        btn.translatesAutoresizingMaskIntoConstraints = NO;
        [btns addObject:btn];
        [self.view addSubview:btn];
    }
    
    NSMutableArray *guides = [NSMutableArray arrayWithCapacity:3];
    for (int i=0;i<3;i++) {
        
        int a = 1;
        
        if (a) {
            UILayoutGuide *guide = [[UILayoutGuide alloc]init];
            [self.view addLayoutGuide:guide];
            [guides addObject:guide];
        }else {
            UIView *guide = [[UIView alloc]init];
            guide.backgroundColor = UIColor.greenColor;
            guide.translatesAutoresizingMaskIntoConstraints = NO;
            [self.view addSubview:guide];
            [guides addObject:guide];
        }
    }

    UILayoutGuide *guide1 = guides[0];
    UILayoutGuide *guide2 = guides[1];
    UILayoutGuide *guide3 = guides[2];
    
    UIButton *btn1 = btns[0];
    UIButton *btn2 = btns[1];
    
    [guide1.leftAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leftAnchor constant:15].active = YES;
    [guide1.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor].active = YES;
    
    [btn1.leftAnchor constraintEqualToAnchor:guide1.rightAnchor].active = YES;
    [btn1.topAnchor constraintEqualToAnchor:guide1.topAnchor].active = YES;
    
    [guide2.leftAnchor constraintEqualToAnchor:btn1.rightAnchor].active = YES;
    [guide2.topAnchor constraintEqualToAnchor:guide1.topAnchor].active = YES;
    
    [btn2.leftAnchor constraintEqualToAnchor:guide2.rightAnchor].active = YES;
    [btn2.topAnchor constraintEqualToAnchor:guide1.topAnchor].active = YES;
    [btn2.widthAnchor constraintEqualToConstant:100].active = YES;
    [btn2.widthAnchor constraintEqualToAnchor:btn1.widthAnchor].active = YES;
    [btn2.heightAnchor constraintEqualToConstant:50].active = YES;
    [btn2.heightAnchor constraintEqualToAnchor:btn1.heightAnchor].active = YES;
    
    [guide3.leftAnchor constraintEqualToAnchor:btn2.rightAnchor].active = YES;
    [guide3.topAnchor constraintEqualToAnchor:guide1.topAnchor].active = YES;
    [guide3.rightAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.rightAnchor constant:-15].active = YES;
    
    [guide3.widthAnchor constraintEqualToAnchor:guide2.widthAnchor].active = YES;
    [guide3.widthAnchor constraintEqualToAnchor:guide1.widthAnchor].active = YES;
    
    [guide3.heightAnchor constraintEqualToAnchor:guide2.heightAnchor].active = YES;
    [guide3.heightAnchor constraintEqualToAnchor:guide1.heightAnchor].active = YES;
    [guide3.heightAnchor constraintEqualToConstant:50].active = YES;
}

这个例子表明在布局时,UILayoutGuide 的使用可以帮助我们减少不必要的视图。但是也可以看出,
虽然 NSLayoutAnchor 类和 NSLayoutConstraint 类属性 active 的使用使得约束的创建简化了很多,但是可读性仍然很差,如果出现错误,查找十分麻烦。

Masonry 框架是不支持 UILayoutGuide 的,不过,其声明了的 MASAdditions 分类中提供了针对这种情况的方法。

typedef NS_ENUM(NSUInteger, MASAxisType) {
    MASAxisTypeHorizontal,
    MASAxisTypeVertical
};
- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
                    withFixedSpacing:(CGFloat)fixedSpacing
                         leadSpacing:(CGFloat)leadSpacing
                         tailSpacing:(CGFloat)tailSpacing;

- (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
                 withFixedItemLength:(CGFloat)fixedItemLength
                         leadSpacing:(CGFloat)leadSpacing
                         tailSpacing:(CGFloat)tailSpacing;

这两个方法可以在水平或垂直方向上排列数组中的视图,区别是视图之间的间隔是固定的值或者视图的宽高是固定值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值