我想在 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];
我应该怎么做?
最佳答案
一些观察:
您创建的这个特定约束是正确的。显然,您不能只设置左约束,而是需要指定所有将明确定义单元格 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
子类来促进跟踪自定义控件的过程,但我想让示例保持简单。如果您不确定约束是否已明确定义,请运行应用程序并在显示 UI 后暂停应用程序并在
(lldb)
提示:po [[UIWindow keyWindow] _autolayoutTrace]
如果任何 View 定义不明确(即是否缺少任何约束),这将通知您。
如果您想查看所有 View 的
frame
是什么,您可以在(lldb)
提示符下输入以下内容:po [[UIWindow keyWindow] recursiveDescription]
确保将所有 subview 的
translatesAutoresizingMaskIntoConstraints
指定为NO
,就像我在上面的代码示例中所做的那样。虽然您可以使用
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/