OGeek|极客世界-中国程序员成长平台

标题: ios - 以编程方式使用 Autolayout 自定义 UITableViewCell 的布局 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 06:05
标题: ios - 以编程方式使用 Autolayout 自定义 UITableViewCell 的布局

我有一个在 iPhone 5s 上运行良好的自定义 UITableViewCell,但是自从这个计划开始以来,我们现在必须更新它以支持 iPhone 6 和 iPhone 6 Plus。

我已经在我的 .xib 文件中使用 Autolayout 解决了大部分升级问题。但是,此单元格没有 .xib,因此我必须以编程方式完成所有操作。为了清楚起见,我暂时在有问题的标签周围画了一个边框

这是 iPhone 5S 上的样子

label with good positioning on iPhone 5s

这是它在 iPhone 6 上的样子

problematic label positioning on iPhone 6

这些表格 View 是可展开/可折叠的。在屏幕截图中,您会看到它已展开。

这是相关代码:

#import "LotsDetailTableViewCell.h"
#import "MSCellAccessory.h"


@interface LotsDetailTableViewCell ()

@property (nonatomic, strong) NSArray *data;
@property (nonatomic, strong) UIView *detailView;

@end

const float LABEL_HEIGHT = 22.0f;

@implementation LotsDetailTableViewCell

- (id)initWithDataNSArray *)data reuseIdentifierNSString *)reuseIdentifier
{
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (self) {
        self.data = data;
        [self setupDetailView];
        self.textLabel.textColor = RGB(39, 143, 191);
        self.textLabel.font = [UIFont fontWithName"HelveticaNeue-Light" size:16.0];

        self.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        self.clipsToBounds = true;

    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];

    self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x,
                                      self.textLabel.frame.origin.y,
                                      self.textLabel.frame.size.width,
                                      43.5f);
   self.accessoryView.frame = CGRectMake(self.accessoryView.frame.origin.x, 6, 32, 32);
}

#pragma mark Detail View

- (void)setupDetailView
{
    self.detailView = [[UIView alloc] init];

    UILabel *previousLabel;

    for (NSObject *detail in self.data) {
        CGFloat frameY;
        NSString *keyText;
        NSString *valueText;

        if([detail isKindOfClass:[NSString class]]){
            keyText = @"";
            valueText = (NSString *)detail;
        } else if([detail isKindOfClass:[NSDictionary class]]){
            keyText = ((NSDictionary *)detail)[@"key"];
            valueText = [(NSDictionary *)detail objectForKey"value"];
        }

        if (previousLabel) {
            frameY = previousLabel.frame.origin.y+previousLabel.frame.size.height;
        } else {
            frameY = self.frame.origin.y+44.0f+[self.data indexOfObject:detail]*LABEL_HEIGHT;
        }

        UILabel *keyLabel = [[UILabel alloc] initWithFrame:
                             CGRectMake(self.frame.size.width*.05, frameY, self.frame.size.width*.45, [self heightForValueLabel:valueText])
                             ];

        UILabel *valueLabel = [[UILabel alloc] initWithFrame:
                           CGRectMake(self.frame.size.width*.5, frameY, self.frame.size.width*.45, [self heightForValueLabel:valueText])
                           ];

        valueLabel.lineBreakMode = NSLineBreakByWordWrapping;
        valueLabel.numberOfLines = 0;
        keyLabel.lineBreakMode = NSLineBreakByWordWrapping;
        keyLabel.numberOfLines = 0;
        valueLabel.textAlignment = NSTextAlignmentRight;
        keyLabel.font = [UIFont fontWithName"HelveticaNeue-Light" size:12.0];
        valueLabel.font = [UIFont fontWithName"HelveticaNeue-Bold" size:12.0];
        keyLabel.textColor = RGB(119, 119, 119);
        valueLabel.textColor = RGB(39, 143, 191);
        keyLabel.text = keyText;
        valueLabel.text = valueText;

        valueLabel.layer.borderColor = [RGB(178, 178, 178) CGColor];
        valueLabel.layer.borderWidth = 1.0f;

        [self.detailView addSubview:keyLabel];
        [self.detailView addSubview:valueLabel];


        previousLabel = valueLabel;
    }

    [self addSubview:self.detailView];
}

- (CGFloat)heightForValueLabelNSString *)text
{
    return [[self class] heightForValueLabel:text width:self.frame.size.width*.5];
}

+ (CGFloat)heightForValueLabelNSString *)text widthCGFloat)width
{
    CGSize constrainedSize = CGSizeMake(width, CGFLOAT_MAX);

    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          [UIFont fontWithName"HelveticaNeue-Bold" size:12.0], NSFontAttributeName,
                                          nil];

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:text attributes:attributesDictionary];

    CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];

    return requiredHeight.size.height+5.0;
}

+ (CGFloat)heightForDataNSArray*)data widthCGFloat)width
{
    CGFloat height = 0.0;

    for (NSObject *detail in data) {
        NSString *valueText;

        if([detail isKindOfClass:[NSString class]]){
            valueText = (NSString *)detail;
        } else if([detail isKindOfClass:[NSDictionary class]]){
            valueText = ((NSDictionary *)detail)[@"value"];
        }

        height = height + [self heightForValueLabel:valueText width:width];
    }

    return height;
}

@end

大部分相关的绘图都是在 setupDetailView 方法中进行的。

我想要什么:我希望标签与 tableviewcell 的右侧对齐,以充分利用可用空间。

我尝试了什么:我尝试使用以下 co 以编程方式在 setupDetailView 中添加 NSLayoutConstraint

NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:valueLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:1.0];

[valueLabel addConstraint:constraint];

[self needsUpdateConstraints];

但这会导致运行时崩溃。

如果我的问题可以在没有自动布局的情况下轻松解决,我不反对。

编辑:如果我尝试添加约束,它就会爆炸:

2015-03-25 14:19:04.047 App[35277:10763464] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2015-03-25 14:19:04.048 App[35277:10763464] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1>
    Container hierarchy: 
<LotsDetailTableViewCell: 0x7faf50494840; baseClass = UITableViewCell; frame = (0 0; 320 44); layer = <CALayer: 0x7faf50494c50>>
   | <UITableViewCellContentView: 0x7faf5049c070; frame = (0 0; 320 44); gestureRecognizers = <NSArray: 0x7faf504a2530>; layer = <CALayer: 0x7faf50455b60>>
    View not found in container hierarchy: <UILabel: 0x7faf50499a50; frame = (156 44; 144 19.304); text = '8050'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7faf50499870>>
    That view's superview: NO SUPERVIEW
2015-03-25 14:19:04.058 App[35277:10763464] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view.  Does the constraint reference something from outside the subtree of the view?  That's illegal. constraint:<NSLayoutConstraint:0x7faf5049a630 UILabel:0x7faf50499a50'8050'.trailing == LotsDetailTableViewCell:0x7faf50494840'LotDetailInfoCell'.right + 1> view:<LotsDetailTableViewCell: 0x7faf50494840; baseClass = UITableViewCell; frame = (0 0; 320 44); layer = <CALayer: 0x7faf50494c50>>'



Best Answer-推荐答案


将 leftConstarint 添加为您的标签后,将其添加为 subview 。

[_label setTranslatesAutoresizingMaskIntoConstraints:NO];


NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:_label
                                                                  attribute:NSLayoutAttributeLeft
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:[_label superview]
                                                                  attribute:NSLayoutAttributeLeft
                                                                 multiplier:1.0
                                                                   constant:10];

[_label addConstraint:leftConstraint];

[_label superview] 必须是您的 [self view]。//可能。 希望能帮助到你。

关于ios - 以编程方式使用 Autolayout 自定义 UITableViewCell 的布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29256659/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://sqlite.in/) Powered by Discuz! X3.4