为 UITableView 的 tableFooterView 设置标签 - 使用自动布局

Posted

技术标签:

【中文标题】为 UITableView 的 tableFooterView 设置标签 - 使用自动布局【英文标题】:Setting a label to UITableView's tableFooterView - with autolayout 【发布时间】:2014-09-09 03:01:39 【问题描述】:

当我的表格视图为空时,我想在表格视图页脚中添加一个简单的标签以显示“无内容”消息。当我设置用于 footerView 的 UILabel 和 UIView 的框架时,它工作正常,但现在我试图转换为使用自动布局,但我无法让它工作。

这就是我正在做的事情:

// Create the footer    
UIView *tempFooter = [[UIView alloc] init];
UILabel *atext = [[UILabel alloc] init];
tempFooter.translatesAutoresizingMaskIntoConstraints = NO;
atext.translatesAutoresizingMaskIntoConstraints = NO;

atext.numberOfLines = 0;
[atext setText:@"Add Some Text"];
atext.textAlignment = NSTextAlignmentCenter;
atext.font = [UIFont italicSystemFontOfSize:14];
atext.textColor = [UIColor grayColor];
atext.backgroundColor = [UIColor clearColor];
atext.lineBreakMode = NSLineBreakByWordWrapping;

// add label to footer view, and add constraints
[tempFooter addSubview:atext];
NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
                                                          attribute:NSLayoutAttributeLeft
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:atext attribute:NSLayoutAttributeLeft
                                                         multiplier:1.0
                                                           constant:10.0];

NSLayoutConstraint *tvatt2 = [NSLayoutConstraint constraintWithItem:tempFooter
                                                          attribute:NSLayoutAttributeRight
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:atext
                                                          attribute:NSLayoutAttributeRight
                                                         multiplier:1.0
                                                           constant:10.0];

NSLayoutConstraint *tvatt3 = [NSLayoutConstraint constraintWithItem:tempFooter
                                                          attribute:NSLayoutAttributeTop
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:atext
                                                          attribute:NSLayoutAttributeTop
                                                         multiplier:5.0
                                                           constant:0];

NSLayoutConstraint *tvatt4 = [NSLayoutConstraint constraintWithItem:tempFooter
                                                          attribute:NSLayoutAttributeBottom
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:atext
                                                          attribute:NSLayoutAttributeBottom
                                                         multiplier:1.0
                                                           constant: 0];

[tempFooter addConstraints: @[tvatt1, tvatt2, tvatt3, tvatt4]];


// set the footerview 
self.tview.tableFooterView = tempFooter;

当我运行它时,我遇到了崩溃:

2014-09-08 19:57:16.594 SimpleList[49442:60b] * 中的断言失败 -[UITableView layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2935.137/UIView.m:8794 2014-09-08 19:57:21.073 SimpleList[49442:60b] * 由于未捕获而终止应用程序 异常'NSInternalInconsistencyException',原因:'自动布局 执行 -layoutSubviews 后仍然需要。 UITableView 的 -layoutSubviews 的实现需要调用super

我不确定我做错了什么。我还尝试为self.tview.tableFooterView wrt 和tempFooter 设置约束(固定在所有4 面),但这不会改变崩溃。我也叫:

[self.tview.tableFooterView layoutSubviews];

但这也无济于事。

任何想法我做错了什么?

【问题讨论】:

尝试注释掉这一行,tempFooter.translatesAutoresizingMaskIntoConstraints = NO;看看是否能解决问题。 不,不幸的是导致不同的崩溃:2014-09-08 22:46:19.905 无法同时满足约束。可能以下列表中的至少一个约束是您不想要的...... ( "<0x117137d80 v:><0x117082480 h="--" v="--&" v:> 【参考方案1】:

对于表格视图、它们的单元格或表格页眉和页脚视图(或者对于您的控制器的 self.view),您不应将 translatesAutoresizingMaskIntoConstraints 设置为 NO。可以对这些视图内的视图使用约束(单元格的内容视图或页眉和页脚视图)。我将您的代码的简化版本添加到 viewDidLoad,它按预期工作。请注意,您需要为页脚视图提供一个高度和一个 x 位置(忽略 y 位置和宽度),

    UIView *tempFooter = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 50)];
    UILabel *atext = [[UILabel alloc] init];
    atext.translatesAutoresizingMaskIntoConstraints = NO;
    atext.numberOfLines = 0;
    [atext setText:@"Add Some Text"];
    atext.textAlignment = NSTextAlignmentCenter;
    atext.font = [UIFont italicSystemFontOfSize:14];
    atext.textColor = [UIColor grayColor];
    atext.backgroundColor = [UIColor clearColor];
    atext.lineBreakMode = NSLineBreakByWordWrapping;

    [tempFooter addSubview:atext];
    NSDictionary *dict = NSDictionaryOfVariableBindings(atext);
    [tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[atext]-10-|" options:0 metrics:nil views:dict]];
    [tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[atext]|" options:0 metrics:nil views:dict]];
    self.tableView.tableFooterView = tempFooter;

我不确定你想用你的约束来完成什么,tvatt3。乘数(您有 5 个)对顶部或左侧约束没有任何作用,因为这些属性的值为 0。我使用了视觉约束,而不是您使用的方法,但是当我使用您的代码添加约束时,它也有效。

【讨论】:

谢谢。乘以 5 的乘数是错字(应该是 1)。这似乎可行,但有一个主要问题,即高度固定为 50。如果文本较长,如何调整标题高度?例如试试这个:[atext setText:@"Add Some Text. Now add a lot more text with newlines thrown in for good measure. Does this work beyond a certain height?\n\nNow how do you calculate the height?"]; 完整的页脚不再显示。我尝试在设置页脚之前使用[atext systemLayoutSizeFittingSize: UILayoutFittingExpandedSize] 设置页脚框架,但它崩溃了 我想我已经成功了;我在viewWillLayoutSubviews 中设置了footerView,并使用systemLayoutSizeFittingSize: 设置了页脚的高度。唯一的问题:仍然在调试器中收到“无法同时满足约束”消息。这个看起来很可疑,但不知道它是如何到达那里的:“<0x7fa2d0050d20 h:> 【参考方案2】:

有趣的是,更改 xib 中的 Autoresizing 掩码解决了我的问题。

约束不起作用:

工作:

【讨论】:

经过数小时尝试不同的事情后,这解决了我在UITableView 的页脚和页眉视图中遇到的问题。非常感谢!我永远不会想到这一点。【参考方案3】:

通过实现约束的@rdelmar 解决方案并在下面添加这些行,我能够动态地自动布局表格页脚的宽度和高度。相同的解决方案适用于表头视图。

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    if let tableFooter = tableView.tableFooterView 
        let maxSize = CGSize(width: self.tableView.bounds.size.width,
                             height: CGFloat.greatestFiniteMagnitude)
        let size = tableFooter.systemLayoutSizeFitting(maxSize)
        let height = size.height
        var headerFrame = tableFooter.frame

        // If we don't have this check, viewDidLayoutSubviews() will get
        // repeatedly, causing the app to hang.
        if height != headerFrame.size.height 
            headerFrame.size.height = height
            tableFooter.frame = headerFrame
            tableView.tableFooterView = tableFooter
        
    

P。 S. 我更喜欢 Interface Builder 进行约束设置

【讨论】:

【参考方案4】:

希望对你有帮助

我不确定这一点,但它对我的项目有帮助,首先在contentView 中添加所有内容(所有子视图和约束)

 [self.contentView addSubview:atext]

然后是代码部分

NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
                                                          attribute:NSLayoutAttributeLeft
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:atext attribute:NSLayoutAttributeLeft
                                                         multiplier:1.0
                                                           constant:10.0]; 

左侧属性的代码说明

 temfooter(must be equal) = 1.0*atext +10.0 

即 temfooter 必须等于修改后的 atext ,所以需要确保你的约束没有错。

【讨论】:

谢谢,但问题更多的是关于 UITableView 的 tableFooterView。将视图添加到另一个 UIView 的一般用例非常简单。 @ZS 探索这个链接(constraints.icodeforlove.com) ,它可能对你有所帮助。

以上是关于为 UITableView 的 tableFooterView 设置标签 - 使用自动布局的主要内容,如果未能解决你的问题,请参考以下文章

指定表格页脚时,最后一个单元格上缺少 uitableview 分隔符

将复杂的 UITableView 转换为 UICollectionView

将分组的 UITableView 设置为从给定部分开始?

动态调整UITableView的大小,该大小将显示为不可滚动的内容列表

如果两个 UITableView 被添加为屏幕上的子视图,导航栏只会折叠一个 UITableView

iCarousel + UITableView = cellForRowAtIndexPath indexPath 始终为空