0

我认为这是自动布局的问题。

我创建了一个视图,并在其中创建了一些子视图。

内容视图包含子视图,子视图全部放在一行中。

我想我没有做错什么,但是 content view 的框架总是不正确。

像这样:

2013-08-29 14:13:34.688 AutoLayoutBugTest[4658:c07] pV_content.frame {{0, 208}, {319, 44}}

内容视图的宽度是 319 但不是 320,更改 viewDidLoad 函数中的 'cnt' 参数,框架可能会更糟。

像这样的代码:

@interface ViewController ()
@property (nonatomic, strong) UIView            *pV_content;
@property (nonatomic, strong) NSMutableArray    *Arr_views;
@end

@implementation ViewController

- (void)removeConstraintForCustomView:(UIView *)customView
                             fromView:(UIView *)superView
{
    NSMutableArray *pArr_constraint = [NSMutableArray array];
    for (NSLayoutConstraint *constraint in superView.constraints) {
        if ([constraint.firstItem isEqual:customView]) {
            [pArr_constraint addObject:constraint];
        }
    }
    [superView removeConstraints:pArr_constraint];
    pArr_constraint = nil;
}

- (void)constraintCustomView:(UIView *)customView
            matchWidthOfView:(UIView *)superView
                  withHeight:(CGFloat)height
{
    [self removeConstraintForCustomView:customView fromView:superView];

    customView.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *constraint_y = [NSLayoutConstraint constraintWithItem:customView
                                                                      attribute:NSLayoutAttributeCenterY
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:superView
                                                                      attribute:NSLayoutAttributeCenterY
                                                                     multiplier:1.f
                                                                       constant:0.f];
    [superView addConstraint:constraint_y];

    NSLayoutConstraint *constraint_height = [NSLayoutConstraint constraintWithItem:customView
                                                                         attribute:NSLayoutAttributeHeight
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:superView
                                                                         attribute:NSLayoutAttributeHeight
                                                                        multiplier:0.f
                                                                          constant:height];
    [superView addConstraint:constraint_height];

    NSLayoutConstraint *constraint_left = [NSLayoutConstraint constraintWithItem:customView
                                                                       attribute:NSLayoutAttributeLeft
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:superView
                                                                       attribute:NSLayoutAttributeLeft
                                                                      multiplier:1.f
                                                                        constant:0.f];
    [superView addConstraint:constraint_left];

    NSLayoutConstraint *constraint_width = [NSLayoutConstraint constraintWithItem:customView
                                                                        attribute:NSLayoutAttributeWidth
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:superView
                                                                        attribute:NSLayoutAttributeWidth
                                                                       multiplier:1.f
                                                                         constant:0.f];
    [superView addConstraint:constraint_width];
}

- (void)constraintCustomView:(UIView *)customView
     matchWidthPercentOfView:(UIView *)superView
                    boxCount:(int)boxCount
                    boxIndex:(int)boxIndex
{
    [self removeConstraintForCustomView:customView fromView:superView];

    customView.translatesAutoresizingMaskIntoConstraints = NO;
    NSLayoutConstraint *constraint_top = [NSLayoutConstraint constraintWithItem:customView
                                                                      attribute:NSLayoutAttributeTop
                                                                      relatedBy:NSLayoutRelationEqual
                                                                         toItem:superView
                                                                      attribute:NSLayoutAttributeTop
                                                                     multiplier:1.f
                                                                       constant:customView.frame.origin.y];
    [superView addConstraint:constraint_top];
    constraint_top.priority = UILayoutPriorityFittingSizeLevel;

    NSLayoutConstraint *constraint_height = [NSLayoutConstraint constraintWithItem:customView
                                                                         attribute:NSLayoutAttributeHeight
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:superView
                                                                         attribute:NSLayoutAttributeHeight
                                                                        multiplier:0.f
                                                                          constant:customView.frame.size.height];
    [superView addConstraint:constraint_height];
    constraint_height.priority = UILayoutPriorityFittingSizeLevel;

    if (boxCount == 1) {
        NSLayoutConstraint *constraint_percent_x = [NSLayoutConstraint constraintWithItem:customView
                                                                                attribute:NSLayoutAttributeCenterX
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:superView
                                                                                attribute:NSLayoutAttributeCenterX
                                                                               multiplier:1.f
                                                                                 constant:0.f];
        [superView addConstraint:constraint_percent_x];
        constraint_percent_x.priority = UILayoutPriorityFittingSizeLevel;

        NSLayoutConstraint *constraint_width = [NSLayoutConstraint constraintWithItem:customView
                                                                            attribute:NSLayoutAttributeWidth
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:superView
                                                                            attribute:NSLayoutAttributeWidth
                                                                           multiplier:1.f
                                                                             constant:-4.f];
        [superView addConstraint:constraint_width];
        constraint_width.priority = UILayoutPriorityFittingSizeLevel;
    }
    else {
        if (boxIndex == 0) {
            NSLayoutConstraint *constraint_left = [NSLayoutConstraint constraintWithItem:customView
                                                                               attribute:NSLayoutAttributeLeft
                                                                               relatedBy:NSLayoutRelationEqual
                                                                                  toItem:superView
                                                                               attribute:NSLayoutAttributeLeft
                                                                              multiplier:1.f
                                                                                constant:0.f];
            [superView addConstraint:constraint_left];
            constraint_left.priority = UILayoutPriorityFittingSizeLevel;

            NSLayoutConstraint *constraint_width = [NSLayoutConstraint constraintWithItem:customView
                                                                                attribute:NSLayoutAttributeWidth
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:superView
                                                                                attribute:NSLayoutAttributeWidth
                                                                               multiplier:(2.f / (CGFloat)(2 * boxCount + 1))
                                                                                 constant:-2.f];
            [superView addConstraint:constraint_width];
            constraint_width.priority = UILayoutPriorityFittingSizeLevel;
        }
        else if (boxIndex == boxCount - 1) {
            NSLayoutConstraint *constraint_right = [NSLayoutConstraint constraintWithItem:customView
                                                                                attribute:NSLayoutAttributeRight
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:superView
                                                                                attribute:NSLayoutAttributeRight
                                                                               multiplier:1.f
                                                                                 constant:0.f];
            [superView addConstraint:constraint_right];
            constraint_right.priority = UILayoutPriorityFittingSizeLevel;

            NSLayoutConstraint *constraint_width = [NSLayoutConstraint constraintWithItem:customView
                                                                                attribute:NSLayoutAttributeWidth
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:superView
                                                                                attribute:NSLayoutAttributeWidth
                                                                               multiplier:(2.f / (CGFloat)(2 * boxCount + 1))
                                                                                 constant:-2.f];
            [superView addConstraint:constraint_width];
            constraint_width.priority = UILayoutPriorityFittingSizeLevel;
        }
        else {
            NSLayoutConstraint *constraint_percent_x = [NSLayoutConstraint constraintWithItem:customView
                                                                                    attribute:NSLayoutAttributeCenterX
                                                                                    relatedBy:NSLayoutRelationEqual
                                                                                       toItem:superView
                                                                                    attribute:NSLayoutAttributeCenterX
                                                                                   multiplier:(((CGFloat)(2 * boxIndex + 1)) / (CGFloat)boxCount)
                                                                                     constant:0.f];
            [superView addConstraint:constraint_percent_x];
            constraint_percent_x.priority = UILayoutPriorityFittingSizeLevel;

            NSLayoutConstraint *constraint_width = [NSLayoutConstraint constraintWithItem:customView
                                                                                attribute:NSLayoutAttributeWidth
                                                                                relatedBy:NSLayoutRelationEqual
                                                                                   toItem:superView
                                                                                attribute:NSLayoutAttributeWidth
                                                                               multiplier:(2.f / (CGFloat)(2 * boxCount + 1))
                                                                                 constant:-2.f];
            [superView addConstraint:constraint_width];
            constraint_width.priority = UILayoutPriorityFittingSizeLevel;
        }
    }
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.view.backgroundColor = [UIColor whiteColor];

    self.pV_content = [[UIView alloc] initWithFrame:CGRectMake(0.f,
                                                               0.f,
                                                               self.view.frame.size.width,
                                                               44.f)];
    self.pV_content.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:self.pV_content];
    [self constraintCustomView:self.pV_content
                      matchWidthOfView:self.view
                            withHeight:44.f];

    int cnt = 5;

    for (int i = 0; i < cnt; i++) {
        UIView *pV_sub = [[UIView alloc] initWithFrame:CGRectMake(0.f,
                                                                  5.f,
                                                                  30.f,
                                                                  35.f)];
        pV_sub.backgroundColor = [UIColor redColor];
        [self.pV_content addSubview:pV_sub];
        [self constraintCustomView:pV_sub
                   matchWidthPercentOfView:self.pV_content
                                  boxCount:cnt
                                  boxIndex:i];
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    NSLog(@"pV_content.frame %@", NSStringFromCGRect(self.pV_content.frame));
}

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

@end
4

1 回答 1

0

来自指南:

约束的形式为“view1.attr1 view2.attr2 * multiplier + constant”。如果您要表达的约束没有第二个视图和属性,请使用 nil 和 NSLayoutAttributeNotAnAttribute。

次要:尝试使用

constraintsWithVisualFormat:options:metrics:views:

例如,如果您有一个视图 testView:

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[testView]|" options:0 metrics:0 views:@{@"testView":self.testView}]];

在 constraintsWithVisualFormat 方法中,您可以设置优先级和变体,例如:@"H:|-(0@100)-[testView(100)]-(0@100)-|"。此 testView 具有高优先级,因为未设置优先级参数,但从左右大小到 superview 的 2 个约束具有优先级 100,并且您的视图 testView 不会更改自身框架。您可以像这样设置格式: [testView(50,100)] 在您的代码中意味着:“testView widht 可以是 50 点或 100。 阅读本指南

于 2013-10-14T09:35:20.253 回答