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

标签 ios autolayout

我想在 cellForRowAtIndexPath 中添加一些 View 到我的单元格内容 View 并为它们添加约束,但没有任何效果。我有这样的东西:

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. 您创建的这个特定约束是正确的。显然,您不能只设置左约束,而是需要指定所有将明确定义单元格 subview 的 frame 的约束。例如,不仅定义左侧(或前导)约束,还定义顶部、底部和宽度约束。或者定义左约束加上宽度和高度约束,并指定垂直 y 约束。有很多不同的方法可以做到这一点,但关键是您必须添加所有约束,这些约束将明确定义所有 subview 的 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]
    

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

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

    po [[UIWindow keyWindow] recursiveDescription]
    
  3. 确保将所有 subview 的 translatesAutoresizingMaskIntoConstraints 指定为 NO,就像我在上面的代码示例中所做的那样。

  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;
    }
    

关于iOS 以编程方式为表格 View 单元格内容创建 NSLayoutConstraint,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20317277/

相关文章:

ios - 在最大长度上更改 UITextField 响应程序

ios - 如何仅向另一个文件中的另一个类提供对一个文件中的类的访问(有点像 friend 类功能)

ios - UIViewController布局时如何处理iPhone X底部缝隙

ios - 多屏支持 iOS 8+

autolayout - 切换状态栏时如何重新定位导航/工具栏?

ios - 基于 AutoLayout 的应用程序中的 NSAutoresizingMaskLayoutConstraint 错误

ios - Swift3 中的数组过滤器

ios - 如何防止 Core Data 在 iOS 5 中重复?

ios - 自动布局 4 UILabels 垂直高度根据其内容/文本

ios - 获取 UIImage 的平均颜色