Objective-C简单约束将UILabel对齐到表视图单元格的右上角

时间:2013-03-22 01:39:05

标签: objective-c

我正在尝试以编程方式在表格视图单元格的右上角添加标签。

[label addConstraint:[NSLayoutConstraint
    constraintWithItem:label
    attribute:NSLayoutAttributeRight
    relatedBy:NSLayoutRelationEqual
    toItem:cell
    attribute:NSLayoutAttributeRight
    multiplier:1.0
    constant:0]];

这给出了一个错误,说我引用了视图子树之外的东西,我猜测它是单元格本身?顶部和右部是否需要两个单独的约束?

我更喜欢用约束来做,但我也尝试手动获取单元格宽度来改变标签的位置。我必须在方向更改方法中添加代码的副本,以便用户旋转设备。如果我不能使用约束,我会这样做,但是我无法获得正确的单元格宽度,这就是我尝试过的。

[label setFrame:CGRectMake(cell.frame.size.width-318, 10, 308, 30)];

似乎cell.frame.size.width未获得正确的单元格宽度。

编辑:我计算出单元格宽度是相对于其中的内容的,所以我更改了上面的行来获得完成这项工作的整个tableView tableView.frame.size.width。我仍然希望得到一些关于约束的反馈,看看是否可能。

编辑:这是我设置单元格和标签的方式......

NSString *cellId = @"cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if(cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}

UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake(10, 10, 308, 30)];
label.text = @"Whatever text";

// Contraint added here

[cell.contentView addSubview: label];

编辑:`感谢@frozendevil

只是为了显示我在应用正确约束后用于设置标签宽度的最终代码...

[cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:200]];

2 个答案:

答案 0 :(得分:3)

一般情况下,您不应该在UITableViewCell中限制对单元格本身的视图,而应该限制单元格-contentView。假设您已遵循常规表格视图最佳做法,您的标签-superview应该是单元格的-contentView - 从标签到单元格直接添加约束正在跳过图层。


编辑:在修补这个问题几分钟后,我无法让单个约束样式代码正常运行(edit2:重新运行它,似乎这两种风格对我来说都很合适),但是使用了视觉格式对我有用:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if(!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        UILabel *label = [[UILabel alloc] init];
        label.text = @"Hallo!";
        label.backgroundColor = [UIColor redColor];
        [label sizeToFit];
        label.translatesAutoresizingMaskIntoConstraints = NO;

        [cell.contentView addSubview:label];

        NSDictionary *viewDict = @{@"label" : label};
        [cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[label]|" options:0 metrics:0 views:viewDict]];
        [cell.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:0 views:viewDict]];

        /* Or this!
        [cell.contentView addConstraint:[NSLayoutConstraint constraintWithItem:label
                                                                     attribute:NSLayoutAttributeRight
                                                                     relatedBy:NSLayoutRelationEqual
                                                                        toItem:cell.contentView
                                                                     attribute:NSLayoutAttributeRight
                                                                    multiplier:1.0
                                                                      constant:0]];
        */
    }

    return cell;
}

如果你想要更复杂的东西,最简单的事情可能是创建一个自定义的UIView子类,它在内部放置它并将它添加到单元格的-contentView


附录:

这里有一些处理标签宽度的方法:

一种方法是调用constraintWithItem:...并使用NSLayoutAttributeWidth属性来固定大小。另一种方法是使用视觉格式样式来完成同样的事情。最好的方法是将标签上的抗压强度设置得非常高(使用-[UIView setContentCompressionResistancePriority:forAxis:]),这样它就可以自动调整到其内容,而无需更改任何值。

如果您对自动布局的可视化格式语言感到不舒服,我强烈建议您观看相关的WWDC视频并编写一些虚拟代码以便熟悉它。我发现它是使用autolayout的最有效方式。

答案 1 :(得分:0)

嗯,我觉得这已经回答了吗?但是如果您有UITableViewCell的自定义子类,则可以通过覆盖-layoutSubviews来轻松放置标签:

@implementation MyCell : UITableViewCell

-(void)layoutSubviews
{
    [ super layoutSubviews ] ;

    CGRect bounds = self.contentView.bounds ;
    [ self.label sizeToFit ] ;
    self.label.anchorPoint = (CGPoint){ 1.0f, 0.0f } ;
    self.label.position = (CGPoint){ CGRectGetMaxX( bounds ), CGRectGetMinY( bounds } ;
}

@end