简体   繁体   English

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

[英]Objective-C simple constraint to align UILabel to top right of a table view cell

I'm trying to add a label to the top-right of a table view cell programmatically. 我正在尝试以编程方式在表格视图单元格的右上角添加标签。

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

This gives an error saying that I referenced something outside the subtree of the view which I'm guessing is the cell itself? 这给出了一个错误,说我引用了视图子树之外的东西,我猜测它是单元格本身? Do I need two separate constraints for top and right? 顶部和右侧是否需要两个单独的约束?

I'd prefer to do it right with constraints, however I've also tried manually getting the cell width to change the label's position. 我更喜欢用约束来做正确的事情,但我也尝试手动获取单元格宽度来改变标签的位置。 I would have to add a duplicate of the code in the orientation change method incase the user rotates the device. 我必须在方向更改方法中添加代码的副本,以便用户旋转设备。 I'm open to doing it this way if I can't use constraints, but I'm not able to get the correct width of the cell, this is what I tried. 如果我不能使用约束,我会这样做,但是我无法获得正确的单元格宽度,这就是我尝试过的。

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

It seems cell.frame.size.width is not getting the correct width of the cell. 似乎cell.frame.size.width没有获得正确的单元格宽度。

EDIT: I worked out the cell width is relative to the content within it, so I changed the above line to get the with of the entire tableView tableView.frame.size.width which does the job. 编辑:我计算出单元格宽度是相对于其中的内容,所以我改变了上面的行来获得整个tableView tableView.frame.size.width功能。 I would still like to get some feedback on constraints to see if that's possible. 我仍然希望得到一些关于约束的反馈,看看是否可能。

EDIT: This is how I set up the cell and label... 编辑:这是我设置单元格和标签的方式......

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];

EDIT: `Thanks to @frozendevil 编辑: `感谢@frozendevil

Just to show the final code I used to set the width of the label after applying the correct constrains... 只是为了显示我在应用正确约束后用于设置标签宽度的最终代码...

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

In general you shouldn't be constraining views in a UITableViewCell against the cell itself, but the cell's -contentView . 一般来说,你不应该在UITableViewCell中限制单元格本身的视图,而应该限制单元格的-contentView Assuming you've followed general table view best practices, your label's -superview should be the cell's -contentView —adding constraints from the label to the cell directly is skipping a layer. 假定您遵循一般的表视图的最佳实践,你的标签的-superview应该是小区的-contentView从标签到小区直接被跳过层-adding约束。


Edit: In tinkering with this problem for a few minutes I was unable to get the single constraint style code to behave properly (edit2: re-running it, it seems as though both flavors are working for me), but using the visual format worked for me: 编辑:在修补这个问题几分钟后,我无法让单个约束样式代码正常运行(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;
}

If you want something more complex the easiest thing to do may be to create a custom UIView subclass that lays itself out internally and add it to the cell's -contentView . 如果你想要更复杂的东西,最简单的事情可能是创建一个自定义的UIView子类,它在内部放置它并将它添加到单元格的-contentView


Addendum: 附录:

There're a handful of ways to handle the width of the label here: 这里有一些处理标签宽度的方法:

One is to call constraintWithItem:... and use the NSLayoutAttributeWidth attribute to pin the size. 一种是调用constraintWithItem:...并使用NSLayoutAttributeWidth属性来固定大小。 Another would be to use the visual format style to do essentially the same thing. 另一种方法是使用视觉格式样式来完成同样的事情。 The best would be to set the compression resistance on the label very high (using -[UIView setContentCompressionResistancePriority:forAxis:] ), so that it automatically adjusts to its contents without the need to change any values. 最好的方法是将标签上的压缩阻力设置得非常高(使用-[UIView setContentCompressionResistancePriority:forAxis:] ),这样它就可以自动调整到其内容,而无需更改任何值。

If you're uncomfortable with the visual format language for autolayout I would highly recommend watching the relevant WWDC videos and writing some dummy code to get comfortable with it. 如果您对自动布局的可视化格式语言感到不舒服,我强烈建议您观看相关的WWDC视频并编写一些虚拟代码以使其变得舒适。 I've found it to be the most productive way to use autolayout. 我发现它是使用autolayout最有效的方法。

Well I think this is answered already? 嗯,我觉得这已经回答了? But if you have a custom subclass of UITableViewCell, placing your label properly is easy by overriding -layoutSubviews : 但是如果你有一个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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM