iOS为表格节标题添加约束

时间:2013-01-30 19:57:06

标签: ios objective-c uitableview constraints

我正在使用分组表,并使用tableView:viewForHeaderInSection:方法在部分中自定义标题,并使用tableView:heightForHeaderInSection:。

设置高度。

我创建了一个视图并在其中放置了一个标签:

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {


    // Create a custom title view.
    UIView *ctv;
    UILabel *titleLabel;

    // Set the name.
    {...} // Code not relevant

    // If an iPhone.
    if ([Config isPhone]) {
        ctv = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 14, 320, 36)];
    }
    // If an iPad
    else {
        ctv = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 768, 75)];
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 544, 55)];
    }

    // Config the label.
    {...} // Code not relevant

    // Center the items.
    ctv.center = CGPointMake(tableView.center.x, ctv.center.y);
    titleLabel.center = ctv.center;

    // Add the label to the container view.
    [ctv addSubview:titleLabel];

    // Return the custom title view.
    return ctv;


}

这一切都很有效,直到您旋转屏幕。这个位置已经关闭。我意识到这是因为当视图处于另一个方向时视图处于居中状态,导致中心的计算不再正确。解决方案应该是添加约束。我尝试在下面添加约束:

NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(ctv);
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|[ctv]|"
                         options:0
                         metrics:nil
                         views:viewsDictionary
                       ];
[tableView addConstraints:constraints];

但是当我这样做尝试下面的方法时,我得到没有父视图与它相关联,这完全合理,因为它在技术上没有被添加到视图中被返回。所以我想我会尝试以这种方式添加约束:

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:ctv
                                     attribute:NSLayoutAttributeCenterX
                                     relatedBy:NSLayoutRelationEqual
                                        toItem:tableView
                                     attribute:NSLayoutAttributeCenterX
                                    multiplier:1.0
                                      constant:0
                                      ];
[tableView addConstraint:constraint];

但这一个也有错误。我已经尝试将tableView变量切换到全局表属性,但它给出了相同的结果。我还试图弄清楚如何在视图中添加约束加载方法,但它失败了,因为我无法弄清楚如何从表对象返回表的节头。我的最后一个想法是在约束中设置表格的宽度,并设置一个以整个表为中心。这个过程有效但现在我的应用程序中间有一个丑陋的滚动,当它处于横向方向时。所以问题是,在加载这些约束之后,我在何处/如何访问各个节标题?我仍然是Objective-C的新手,所以任何帮助都表示赞赏。

*****基于rdelmar的新代码建议****

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *ctv = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"groupHeader"];
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 544, 55)];
    [titleLabel setTranslatesAutoresizingMaskIntoConstraints: NO];
    NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:ctv
                                        attribute:NSLayoutAttributeCenterX
                                        relatedBy:0
                                          toItem:titleLabel
                                        attribute:NSLayoutAttributeCenterX
                                       multiplier:1.0
                                         constant:0
                                      ];
    [ctv addConstraints:@[constraint]];
    titleLabel.text = @"string";
    [ctv addSubview:titleLabel];
    return ctv;
}

但就像我提到的那样,它给了我一个“约束必须包含第一个布局项”的错误。

2 个答案:

答案 0 :(得分:1)

我在最近添加标签和UIActivityIndi​​catorView的项目中这样做了:

-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *headerView = [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0,0, 250, 20)];
    [label setTranslatesAutoresizingMaskIntoConstraints:NO];
    NSLayoutConstraint *con1 = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:label attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *con2 = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeLeft relatedBy:0 toItem:label attribute:NSLayoutAttributeLeading multiplier:1 constant:-10];
    [headerView addConstraints:@[con1,con2]];
    label.text = @"Pick an Activity from the List";
    label.backgroundColor = [UIColor clearColor];
    [headerView addSubview:label];
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    [spinner setTranslatesAutoresizingMaskIntoConstraints:NO];
    if (activityIndicatorShouldStop == NO) [spinner startAnimating];
    [headerView addSubview:spinner];
    NSLayoutConstraint *con3 = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeCenterY relatedBy:0 toItem:spinner attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *con4 = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeRight relatedBy:0 toItem:spinner attribute:NSLayoutAttributeTrailing multiplier:1 constant:10];
    [headerView addConstraints:@[con3,con4]];
    return headerView;
}

答案 1 :(得分:0)

如果你无法使约束起作用,你的原始代码补充了自动调整掩码(灵活的左右边距)就可以完成这项工作。

更简单的解决方案是将UILabel作为标题视图返回,并使用居中文本。

您对约束的第一次尝试不起作用,因为您设置错误。

表视图负责设置标题视图的框架。您需要担心标题标题中的位置。这个的VFL是"|titleLabel|" - 标题标签的大小应该是它的超级视图,标题视图。