iOS以编程方式为表视图单元格内容创建NSLayoutConstraint

时间:2013-12-01 21:08:12

标签: ios autolayout

我想在cellForRowAtIndexPath中添加一些视图到我的单元格内容视图,对于它们的约束,但没有任何作用。我有这样的事情:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:imageView
                                  attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeLeft multiplier:1.0f constant:10.0f];

[cell.contentView addConstraint:constraint];

我该怎么做?

1 个答案:

答案 0 :(得分:49)

有几点意见:

  1. 您创建此特定约束是正确的。显然,您不能只设置左约束,但需要指定将明确定义单元格子视图的frame的所有约束。例如,不仅要定义左(或前导)约束,还要定义顶部,底部和宽度约束。或者定义左约束加上宽度和高度约束,并指定垂直y约束。有很多不同的方法,但关键是你必须添加所有的约束,明确定义所有子视图的frame

    例如,您可能会遇到以下内容:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *cellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
        UIImageView *customImageView;
        UILabel *customLabel;
    
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
            customImageView = [[UIImageView alloc] init];
            customImageView.translatesAutoresizingMaskIntoConstraints = NO;
            customImageView.tag = IMAGEVIEWTAG;
            [cell.contentView addSubview:customImageView];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customImageView
                                                                         attribute:NSLayoutAttributeLeading
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeLeft
                                                                        multiplier:1.0
                                                                          constant:25.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customImageView
                                                                         attribute:NSLayoutAttributeWidth
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:nil
                                                                         attribute:NSLayoutAttributeNotAnAttribute
                                                                        multiplier:1.0
                                                                          constant:30.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customImageView
                                                                         attribute:NSLayoutAttributeTop
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeTop
                                                                        multiplier:1.0
                                                                          constant:3.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customImageView
                                                                         attribute:NSLayoutAttributeBottom
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeBottom
                                                                        multiplier:1.0
                                                                          constant:-3.0]];
    
            customLabel = [[UILabel alloc] init];
            customLabel.translatesAutoresizingMaskIntoConstraints = NO;
            customLabel.tag = LABELTAG;
            [cell.contentView addSubview:customLabel];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customLabel
                                                                         attribute:NSLayoutAttributeLeading
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:customImageView
                                                                         attribute:NSLayoutAttributeTrailing
                                                                        multiplier:1.0
                                                                          constant:10.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customLabel
                                                                         attribute:NSLayoutAttributeTrailing
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeTrailing
                                                                        multiplier:1.0
                                                                          constant:-10.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customLabel
                                                                         attribute:NSLayoutAttributeTop
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeTop
                                                                        multiplier:1.0
                                                                          constant:3.0]];
    
            [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:customLabel
                                                                         attribute:NSLayoutAttributeBottom
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:cell.contentView
                                                                         attribute:NSLayoutAttributeBottom
                                                                        multiplier:1.0
                                                                          constant:-3.0]];
    
        }
        else {
            customImageView = (id)[cell.contentView viewWithTag:IMAGEVIEWTAG];
            customLabel     = (id)[cell.contentView viewWithTag:LABELTAG];
        }
    
        customImageView.image = ...;
        customLabel.text      = ...;
    
        return cell;
    }
    

    显然,您经常使用UITableViewCell子类来促进跟踪自定义控件的过程,但我希望保持示例简单。

  2. 如果您不确定是否已明确定义约束,请运行应用程序,并在呈现UI后,暂停应用程序并在(lldb)提示符下输入以下内容:

    po [[UIWindow keyWindow] _autolayoutTrace]
    

    如果任何视图被明确定义(即是否缺少任何约束),这将通知您。

    如果您想查看frame对所有观看的内容,可以在(lldb)提示符下输入以下内容:

    po [[UIWindow keyWindow] recursiveDescription]
    
  3. 请务必为所有子视图指定translatesAutoresizingMaskIntoConstraintsNO,就像我在上面的代码示例中所做的那样。

  4. 虽然您可以使用constraintWithItem定义约束,但人们通常会使用constraintsWithVisualFormat,因为您通常可以更简洁地定义约束。将上面的代码示例与此代码示例进行对比:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *cellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
        UIImageView *customImageView;
        UILabel *customLabel;
    
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    
            customImageView = [[UIImageView alloc] init];
            customImageView.translatesAutoresizingMaskIntoConstraints = NO;
            customImageView.tag = IMAGEVIEWTAG;
            [cell.contentView addSubview:customImageView];
    
            customLabel = [[UILabel alloc] init];
            customLabel.translatesAutoresizingMaskIntoConstraints = NO;
            customLabel.tag = LABELTAG;
            [cell.contentView addSubview:customLabel];
    
            NSDictionary *views = NSDictionaryOfVariableBindings(customImageView, customLabel);
            [cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-25-[customImageView(30)]-[customLabel]|" options:0 metrics:nil views:views]];
            [cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-3-[customImageView]-3-|"                 options:0 metrics:nil views:views]];
            [cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-3-[customLabel]-3-|"                     options:0 metrics:nil views:views]];
        }
        else {
            customImageView = (id)[cell.contentView viewWithTag:IMAGEVIEWTAG];
            customLabel     = (id)[cell.contentView viewWithTag:LABELTAG];
        }
    
        customImageView.image = ...;
        customLabel.text      = ...;
    
        return cell;
    }