为啥我的 UITableViewCell 的方向会改变 AutoLayout?

Posted

技术标签:

【中文标题】为啥我的 UITableViewCell 的方向会改变 AutoLayout?【英文标题】:Why does an orientation change AutoLayout for my UITableViewCell?为什么我的 UITableViewCell 的方向会改变 AutoLayout? 【发布时间】:2015-06-10 15:35:03 【问题描述】:

我正在尝试在带有 Objective-C 的 UITableViewCell 中使用 AutoLayout。我没有使用 nib/xib/storyboard。我在代码中创建我的视图。

这是我的 UITableViewCell:

@implementation SettlementTableViewCell

- (instancetype) initWithReuseIdentifier:(NSString *)reuseIdentifier 
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
    if (!self) return nil;

    [self setSelectionStyle:UITableViewCellSelectionStyleNone];

    _order = [[UILabel alloc] init];
    [_order setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_order setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]];
    [[self contentView] addSubview:_order];

    _amount = [[UILabel alloc] init];
    [_amount setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_amount setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]];
    [_amount setTextAlignment:NSTextAlignmentRight];
    [[self contentView] addSubview:_amount];

    _pickupDate = [[UILabel alloc] init];
    [_pickupDate setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_pickupDate setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
    [[self contentView] addSubview:_pickupDate];

    _pickupLocation = [[UILabel alloc] init];
    [_pickupLocation setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_pickupLocation setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
    [_pickupLocation setAdjustsFontSizeToFitWidth:YES];
    [_pickupLocation setTextAlignment:NSTextAlignmentRight];
    [[self contentView] addSubview:_pickupLocation];

    _deliveryDate = [[UILabel alloc] init];
    [_deliveryDate setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_deliveryDate setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
    [[self contentView] addSubview:_deliveryDate];

    _deliveryLocation = [[UILabel alloc] init];
    [_deliveryLocation setTranslatesAutoresizingMaskIntoConstraints:NO];
    [_deliveryLocation setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]];
    [_deliveryLocation setAdjustsFontSizeToFitWidth:YES];
    [_deliveryLocation setTextAlignment:NSTextAlignmentRight];
    [[self contentView] addSubview:_deliveryLocation];

    [self setNeedsUpdateConstraints];

    return self;


- (void) updateConstraints 
    [super updateConstraints];

    UIEdgeInsets padding = UIEdgeInsetsMake(5, 20, -5, -20);

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_order attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationLessThanOrEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeLeft multiplier:1 constant:padding.left]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_order attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeTop multiplier:1 constant:padding.top]];

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_amount attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeTop multiplier:1 constant:padding.top]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_amount attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeRight multiplier:1 constant:padding.right]];

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupDate attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeLeft multiplier:1 constant:padding.left]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupDate attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:_order attribute:NSLayoutAttributeBottom multiplier:1 constant:padding.top]];

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupLocation attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:_pickupDate attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupLocation attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual
                                                                      toItem:_pickupDate attribute:NSLayoutAttributeRight multiplier:1.0 constant:2]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupLocation attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeRight multiplier:1 constant:padding.right]];

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryDate attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeLeft multiplier:1 constant:padding.left]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryDate attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:_pickupDate attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryDate attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeBottom multiplier:1 constant:padding.bottom]];

    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryLocation attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
                                                                      toItem:_deliveryDate attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryLocation attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeBottom multiplier:1 constant:padding.bottom]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryLocation attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationGreaterThanOrEqual
                                                                      toItem:_deliveryDate attribute:NSLayoutAttributeRight multiplier:1.0 constant:2]];
    [[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryLocation attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual
                                                                      toItem:[self contentView] attribute:NSLayoutAttributeRight multiplier:1 constant:padding.right]];

//    [_order setBackgroundColor:[UIColor redColor]];
//    [_amount setBackgroundColor:[UIColor orangeColor]];
//    [_pickupDate setBackgroundColor:[UIColor yellowColor]];
//    [_pickupLocation setBackgroundColor:[UIColor greenColor]];
//    [_deliveryDate setBackgroundColor:[UIColor blueColor]];
//    [_deliveryLocation setBackgroundColor:[UIColor purpleColor]];


@end

这是 UIViewController:

@interface Settlement : NSObject
@property (nonatomic, strong) NSString *orderId;
@property (nonatomic, strong) NSString *amount;
@property (nonatomic, strong) NSString *pickupDate;
@property (nonatomic, strong) NSString *deliveryDate;
@property (nonatomic, strong) NSString *pickupLocation;
@property (nonatomic, strong) NSString *deliveryLocation;
@end

@implementation Settlement
@end

@interface SettlementsViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) NSMutableArray *rows;
@property (nonatomic, strong) UITableView *tableView;
@end

@implementation SettlementsViewController

- (instancetype) init 
    self = [super init];
    if (!self) return nil;

    [self setTitle:@"Settlements"];

    _rows = [[NSMutableArray alloc] initWithCapacity:5];

    Settlement *set = [[Settlement alloc] init];
    [set setOrderId:@"01234567"];
    [set setAmount:@"$9999.99"];
    [set setPickupDate:@"02/23/2015 0800"];
    [set setDeliveryDate:@"02/25/2015 1100"];
    [set setPickupLocation:@"Point Field Landing on the Severn, MD"];
    [set setDeliveryLocation:@"Winchester-on-the-Severn, MD"];
    [_rows addObject:set];

    set = [[Settlement alloc] init];
    [set setOrderId:@"0006181"];
    [set setAmount:@"$3.42"];
    [set setPickupDate:@"12/26/2013 1040"];
    [set setDeliveryDate:@"02/13/2014 0800"];
    [set setPickupLocation:@"Irondale, AL"];
    [set setDeliveryLocation:@"Lithonia, GA"];
    [_rows addObject:set];

    set = [[Settlement alloc] init];
    [set setOrderId:@"0002586"];
    [set setAmount:@"$1.66"];
    [set setPickupDate:@"09/27/2012 1350"];
    [set setDeliveryDate:@"02/09/2013 1115"];
    [set setPickupLocation:@"Decatur, AL"];
    [set setDeliveryLocation:@"Birmingham, AL"];
    [_rows addObject:set];

    set = [[Settlement alloc] init];
    [set setOrderId:@"0002586"];
    [set setAmount:@"$41.22"];
    [set setPickupDate:@"11/08/2013 1608"];
    [set setDeliveryDate:@"11/11/2013 0000"];
    [set setPickupLocation:@"Birmingham, AL"];
    [set setDeliveryLocation:@"Simi Valley, CA"];
    [_rows addObject:set];

    set = [[Settlement alloc] init];
    [set setOrderId:@"0002586"];
    [set setAmount:@"$41.22"];
    [set setPickupDate:@"11/08/2013 1608"];
    [set setDeliveryDate:@"11/11/2013 0000"];
    [set setPickupLocation:@"Birmingham, AL"];
    [set setDeliveryLocation:@"Simi Valley, CA"];
    [_rows addObject:set];

    return self;


- (void) loadView 
    [super loadView];

    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    [_tableView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
    [_tableView setDelegate:self];
    [_tableView setDataSource:self];
    [_tableView setEstimatedRowHeight:72.0f];
    [_tableView setRowHeight:UITableViewAutomaticDimension];
    [[self view] addSubview:_tableView];


- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  return _rows.count; 

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    SettlementTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) cell = [[SettlementTableViewCell alloc] initWithReuseIdentifier:@"cell"];

    Settlement *settlement = [_rows objectAtIndex:indexPath.row];
    [[cell order] setText:[settlement orderId]];
    [[cell amount] setText:[settlement amount]];
    [[cell pickupDate] setText:[settlement pickupDate]];
    [[cell deliveryDate] setText:[settlement deliveryDate]];
    [[cell pickupLocation] setText:[settlement pickupLocation]];
    [[cell deliveryLocation] setText:[settlement deliveryLocation]];

    return cell;


@end

当屏幕第一次加载时,我得到这个布局:

当我更改为横向时,我得到:

当我切换回纵向时,我得到:

最后一个状态是我真正想要的布局。如何使初始布局看起来像一个后方向更改?我错过了什么?

这只是我能做的一个例子。我可以提供一个显示该问题的正在运行的项目,但我不知道最好的方法。留下评论告诉我怎么做,我会把它放在那里。

谢谢!

【问题讨论】:

【参考方案1】:

我继续玩这个。如果我在两个日期字段上明确设置宽度,我会得到我想要的布局:

[[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_pickupDate attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual
                                                                  toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:120.0]];
[[self contentView] addConstraint:[NSLayoutConstraint constraintWithItem:_deliveryDate attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual
                                                                  toItem:_pickupDate attribute:NSLayoutAttributeWidth multiplier:1 constant:0]];

谁能解释为什么内在内容大小不够好?谢谢!

【讨论】:

以上是关于为啥我的 UITableViewCell 的方向会改变 AutoLayout?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的自定义 UITableViewCell 没有显示?

为啥手动重用的 UITableViewCell 在重新加载行时会消失?

为啥我的自定义 UITableViewCell 在 cellForRowAtIndexPath 中为空?

为啥我的自定义 UITableViewcell 没有显示?

UITableViewCell为啥会有自动布局约束冲突

为啥在单元测试中使用 UITableViewCell 会导致 Trace/BPT 陷阱?