UITableViewHeaderFooterView 的正确子类化和自动布局

Posted

技术标签:

【中文标题】UITableViewHeaderFooterView 的正确子类化和自动布局【英文标题】:Correct subclassing and autolayout of UITableViewHeaderFooterView 【发布时间】:2014-03-01 05:20:51 【问题描述】:

这是我在 UITableViewHeaderFooterView 视图中设置内容的方法。

- (id)initWithFrame:(CGRect)frame

self = [super initWithFrame:frame];
if (self) 
    [self.contentView addSubview:self.createHeader];

return self;


- (UIView *)createHeader

  UIView *headerContainer = [[UIView alloc] init];
  headerContainer.backgroundColor = [UIColor blackColor];
  UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
  label.translatesAutoresizingMaskIntoConstraints = NO;
  label.text = @"titlename";

  [headerContainer addSubview:label];

  NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:label
                                                                   attribute:NSLayoutAttributeLeading
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:headerContainer
                                                              attribute:NSLayoutAttributeLeft
                                                             multiplier:1.f constant:16.f];
[headerContainer addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:label
                                          attribute:NSLayoutAttributeTrailing
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:headerContainer
                                          attribute:NSLayoutAttributeRight
                                         multiplier:1.f constant:-16.f];
[headerContainer addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:label
                                          attribute:NSLayoutAttributeTop
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:headerContainer
                                          attribute:NSLayoutAttributeTop
                                         multiplier:1.f constant:0.f];
[headerContainer addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:label
                                          attribute:NSLayoutAttributeBottom
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:headerContainer
                                          attribute:NSLayoutAttributeBottom
                                         multiplier:1.f constant:0.f];
[headerContainer addConstraint:constraint];

return headerContainer;

我收到此自动布局错误:

 Probably at least one of the constraints in the following list is one you don't want. 
 Try this: (1) look at each constraint and try to figure out which you don't expect; 
 (2) find the code that added the unwanted constraint or constraints and fix it. 
 (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand,
 refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 

(
"<NSLayoutConstraint:0xd4bd7e0 UILabel:0x17254980.leading == UIView:0x172547d0.left + 16>",
"<NSLayoutConstraint:0xd4bd810 UILabel:0x17254980.trailing == UIView:0x172547d0.right - 16>",
"<NSAutoresizingMaskLayoutConstraint:0xd402510 h=--& v=--& H:[UIView:0x172547d0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xd4bd810 UILabel:0x17254980.trailing == UIView:0x172547d0.right - 16>

【问题讨论】:

【参考方案1】:

线索就在错误中:translatesAutoresizingMaskIntoConstraints

我会说您需要将以下行添加到您的 createHeader 方法中:

headerContainer.translatesAutoresizingMaskIntoConstraints = NO;

这是第二个想法。看起来您想将标签居中在 headerContainer 中,对吗?而不是:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:label
                                                                   attribute:NSLayoutAttributeLeading
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:headerContainer
                                                              attribute:NSLayoutAttributeLeft
                                                             multiplier:1.f constant:16.f];
[headerContainer addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:label
                                          attribute:NSLayoutAttributeTrailing
                                          relatedBy: NSLayoutRelationLessThanOrEqual
                                             toItem:headerContainer
                                          attribute:NSLayoutAttributeRight
                                         multiplier:1.f constant:-16.f];
[headerContainer addConstraint:constraint];

试试:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:label
                                                                   attribute:NSLayoutAttributeLeading
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:headerContainer
                                                              attribute:NSLayoutAttributeLeft
                                                             multiplier:1.f constant:16.f];
[headerContainer addConstraint:constraint];

constraint = [NSLayoutConstraint constraintWithItem:label
                                          attribute:NSLayoutAttributeTrailing
                                          relatedBy:NSLayoutRelationEqual
                                             toItem:label
                                          attribute:NSLayoutAttributeLeading
                                         multiplier:1.f constant:0];
[headerContainer addConstraint:constraint];

【讨论】:

执行此操作后,错误消失但标题的定位已关闭。 是的,我调整了答案。在视图上设置该属性时,通常需要添加一些约束来弥补在禁用 translatesAutoresizingMaskIntoConstraints 时丢失的约束。标题的位置是否在其超级视图中关闭? 很酷,谢谢!你知道我怎样才能找到默认约束吗? 我认为您不需要默认约束。这就是造成你的问题的原因。您想添加一些额外的约束来适当地调整 headerContainer 的大小和位置。我建议阅读 Visual Format Language,因为它非常适合指定这些类型的约束。

以上是关于UITableViewHeaderFooterView 的正确子类化和自动布局的主要内容,如果未能解决你的问题,请参考以下文章