以编程方式使用autolayout实现带子视图的uiview子类

时间:2015-05-25 11:11:55

标签: ios objective-c uiview autolayout nslayoutconstraint

我的需求非常通用,我必须实现一个UIView子类,它将UIImageView分组,在屏幕上以x为中心,从顶部开始距离为20,并带有描述的UILabel。 使用界面构建器我没有遇到任何问题,但由于我需要以编程方式进行,所以我会考虑技术和最佳实践。 到目前为止,我想出了这个代码,开始只是想象图像。尽管它是非常基本的,但我无法理解为什么视图不能(如你从屏幕截图中看到的那样)推导出适当的框架,它应该是"偏移的"图像视图中所有边缘上的20个点。

这是我的子类:

标题

@interface ProgrammaticAutolayoutView : UIView

@property (nonatomic, strong) UIImageView *imageView;

@end

实施

#import "ProgrammaticAutolayoutView.h"

@implementation ProgrammaticAutolayoutView{

    BOOL _didUpdateConstraints;
}

- (instancetype)init
{
    return [self initWithFrame:CGRectZero];;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        _didUpdateConstraints = NO;

        _imageView = [UIImageView new];
        [_imageView setTranslatesAutoresizingMaskIntoConstraints: NO];

        [self addSubview: _imageView];
    }
    return self;
}

- (void) updateConstraints{

    if(!_didUpdateConstraints){
        [self setupConstraints];
    }

    [super updateConstraints];
}

- (void) setupConstraints{

    [self.imageView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:50]];

    [self.imageView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:50]];

    [self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:20.0]];

    [self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0]];

    [self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:20.0]];

    [self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:20.0]];

    _didUpdateConstraints = YES;
}

@end

这是我用来实例化和绘制这个uiview子类的代码片段:

    - (void)viewDidLoad {
    [super viewDidLoad];

    ProgrammaticAutolayoutView *test = [[ProgrammaticAutolayoutView alloc] init];
    [test setTranslatesAutoresizingMaskIntoConstraints:NO];
    test.imageView.image = [UIImage imageNamed:@"dmy"];
    test.backgroundColor = [UIColor redColor];

    [self.view addSubview: test];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem: test attribute:NSLayoutAttributeCenterX relatedBy: NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem: test attribute:NSLayoutAttributeCenterY relatedBy: NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];

    [test setNeedsLayout];
    [test layoutIfNeeded];
}

我期待看到子视图从uiimageview的所有边缘偏移20点,但结果完全不同,我没有调试器日志或任何不一致,显然我必须遗漏一些非常基本的东西,但是到目前为止我还不明白。

wrong offset on image view

1 个答案:

答案 0 :(得分:2)

常数描述X和Y偏移。你的4个限制说:

  • 将图像顶部放置在20以下(+ Y 20)红色视图
  • 将图像底部放置在20以下(+ Y 20)红色视图
  • 将imageView的前缘20点放在红色视图的右侧(+ X 20)
  • 将imageView的后缘20点放在红色视图的右侧(+ X 20)

这就是你的照片所示。

要使红色框框成图像,可以使两个常量为负:

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-20.0]];

切换底部和尾随约束中项目的顺序:

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self.imageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:20.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem: self attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.imageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:20.0]];

新建议的限制条件说:

  • 将imageView的底部放在20以上(-Y 20)红色视图
  • 将imageView的后端20点放在红色视图的左侧(-X 20)

  • 将红色底部的20个点(+ Y 20)放在imageView
  • 下面
  • 将红色View 20的后缘放置在imageView右侧(+ X 20)