iOS 以编程方式为表格视图单元格内容创建 NSLayoutConstraint
Posted
技术标签:
【中文标题】iOS 以编程方式为表格视图单元格内容创建 NSLayoutConstraint【英文标题】:iOS create NSLayoutConstraint programmatically for table view cell content 【发布时间】:2013-12-01 21:08:12 【问题描述】:我想在 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];
我应该怎么做?
【问题讨论】:
您是否使用手动添加到单元格的图像视图来执行此操作?在添加自己的控件时,我建议不要使用现有imageView
属性的名称(例如,imageView
、textLabel
和 detailTextLabel
)。或者您是否尝试在现有的 imageView
上执行此操作,我也不建议这样做。
不,这只是示例名称,我为图像视图使用了另一个名称。
【参考方案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
子类来促进跟踪自定义控件的过程,但我想让示例保持简单。
如果您不确定约束是否已明确定义,请运行应用程序并在呈现 UI 后暂停应用程序并在 (lldb)
提示符处输入以下内容:
po [[UIWindow keyWindow] _autolayoutTrace]
这将通知您是否有任何视图定义不明确(即是否缺少任何约束)。
如果您想查看所有视图的frame
是什么,可以在(lldb)
提示符处输入以下内容:
po [[UIWindow keyWindow] recursiveDescription]
确保为所有子视图指定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;
【讨论】:
谢谢。这很有帮助。 从 ios9 开始,您可以使用 NSLayoutAnchor 类来编写“更简洁、更易于阅读”的视觉约束。 @Raiden996 - 是的,这比旧的addConstraint
/constraintWithItem
组合更好,但在这种情况下,我个人仍然会使用 VFL(在三行代码中添加八个约束)。
对于 textViews 如果你想让你的文本适合 textview 也添加这两行: [textView sizeToFit]; [keyTextView layoutIfNeeded];以上是关于iOS 以编程方式为表格视图单元格内容创建 NSLayoutConstraint的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式在 UITableViewCell 上显示删除按钮