2015-05-22 4 views
1

Я пытаюсь создать ячейку таблицы с динамическим размером таблицы. Я прочитал каждый вопрос SO, сайт, статью и пример проекта Github и не могу получить макет, который я хочу без ошибок (в его текущей форме ошибок нет, но конечный результат показан на последнем изображении) ,Dynamic UITableViewCell Производит нежелательные результаты

У меня есть таблица с несколькими разделами. Первый раздел имеет одну ячейку, которая имеет динамический размер. Моя цель - правильно отобразить эту ячейку и без ошибок. Вот два различных визуальных состояний ячейка может иметь:

Вот желаемый вид клетки с Посланием на дне: Cell w/ dynamically sized message

Здесь желательно посмотреть ячейки без сообщения на всех:

Cell w/o message at all

Для кода, показанного ниже, и вот результат:

enter image description here

Вот TableViewController:

// 
// The TableViewController 
// 

#import <Masonry.h> 
#import "CustomCell.h" 
#import "MyViewController.h" 

@interface MyViewController() 

@property (retain, nonatomic) CheckoutHeaderView *headerView; 
@property (retain, nonatomic) CustomCell *customCell; 

@end 


@implementation MyViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.tableView = [[UITableView alloc] init]; 
    self.tableView.delegate = self; 
    self.tableView.dataSource = self; 
    self.tableView.allowsSelection = NO; 
    [self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"customCell"]; 

    [self.view addSubview:self.headerView]; 
    [self.view addSubview:self.tableView]; 

    [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) { 
     make.top.equalTo(self.view); 
     make.left.equalTo(self.view); 
     make.right.equalTo(self.view); 
    }]; 

    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { 
     make.top.equalTo(self.headerView.mas_bottom); 
     make.left.equalTo(self.view); 
     make.right.equalTo(self.view); 
     make.bottom.equalTo(self.view); 
    }]; 

} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    return self.customerCell; 
} 


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static dispatch_once_t onceToken; 
    static CustomCell *customCell; 
    dispatch_once(&onceToken, ^{ 
     customCell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault 
             reuseIdentifier:@"customCell"]; 
     self.customCell = customerCell; 
    }); 

    self.customCell.model = self.model; 

    return [self calculateHeightForConfiguredSizingCell:self.customCell]; 
} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    return 1; 
} 

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell { 
    [sizingCell setNeedsUpdateConstraints]; 
    [sizingCell updateConstraintsIfNeeded]; 

    sizingCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.tableView.bounds), CGRectGetHeight(self.tableView.bounds)); 

    [sizingCell setNeedsLayout]; 
    [sizingCell layoutIfNeeded]; 

    CGFloat height = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; 

    height += 1.0f; 

    return height; 
} 

@end 

Вот класс клеток:

#import "CustomCell.h" 
#import <Masonry.h> 
#import "Label.h" 
#import "Order.h" 
#import "Helper.h" 
#import "Theme.h" 

@interface CustomCell() 

@property (assign, nonatomic) BOOL didSetupConstraints; 

@property (retain, nonatomic) Label *dateOneLabel; 
@property (retain, nonatomic) Label *dateTwoToLabel; 
@property (retain, nonatomic) Label *messageLabel; 

@property (retain, nonatomic) Label *dateOneValue; 
@property (retain, nonatomic) Label *dateTwoToValue; 
@property (retain, nonatomic) Label *messageText; 

@property (retain, nonatomic) NSMutableArray *messageConstraints; 
@property (retain, nonatomic) MASConstraint *pinBottomOfDateTwoLabelToBottomOfContentViewConstraint; 

@end 

@implementation CustomCell 

- (NSMutableArray *)messageConstraints { 
    return _messageConstraints ? _messageConstraints : [@[] mutableCopy]; 
} 

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     [self setup]; 
    } 
    return self; 
} 

- (void)awakeFromNib { 
    [self setup]; 
} 

- (void) setup { 

    self.didSetupConstraints = NO; 

    self.dateOneLabel = [UILabel new]; 
    self.dateOneLabel.text = @"Date One"; 

    self.dateTwoLabel = [UILabel new]; 
    self.dateTwoLabel.text = @"Date Two"; 

    self.messageLabel = [UILabel new]; 
    self.messageLabel.text = @"Message"; 

    self.dateOneValue = [UILabel new]; 
    self.dateTwoToValue = [UILabel new]; 

    // The actual message text label that spans numerous lines. 
    self.messageText = [UILabel new]; 
    self.messageText.numberOfLines = 0; 
    self.messageText.adjustsFontSizeToWidth = NO; 


    [self.contentView addSubview:self.dateOneLabel]; 
    [self.contentView addSubview:self.dateTwoToLabel]; 
    [self.contentView addSubview:self.messageLabel]; 
    [self.contentView addSubview:self.dateOneValue]; 
    [self.contentView addSubview:self.dateTwoToValue]; 
    [self.contentView addSubview:self.messageText]; 
} 

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    [self.contentView setNeedsLayout]; 
    [self.contentView layoutIfNeeded]; 

    self.messageText.preferredMaxLayoutWidth = CGRectGetWidth(self.messageText.frame); 
} 

- (void)updateConstraints { 

    if (!self.didSetupConstraints) { 

     __weak typeof (self.contentView) contentView = self.contentView; 

     // Topmost label, pinned to left side of cell. 
     [self.dateOneLabel mas_remakeConstraints:^(MASConstraintMaker *make) { 
      make.left.equalTo(contentView).with.offset(14); 
      make.right.lessThanOrEqualTo(self.dateOneValue.mas_left).with.offset(-20); 
      make.top.equalTo(contentView).with.offset(14); 
     }]; 

     // Second label, pinned to left side of cell and below first label. 
     [self.dateTwoToLabel mas_remakeConstraints:^(MASConstraintMaker *make) { 
      make.left.equalTo(self.dateOneLabel); 
      make.top.equalTo(self.dateOneLabel.mas_bottom).with.offset(6); 
      make.right.lessThanOrEqualTo(self.dateTwoToValue.mas_left).with.offset(-20); 
     }]; 

     // First date value, pinned to right of cell and baseline of its label. 
     [self.dateOneValue mas_remakeConstraints:^(MASConstraintMaker *make) { 
      make.right.equalTo(contentView).with.offset(-14).priorityHigh(); 
      make.baseline.equalTo(self.dateOneLabel); 
     }]; 

     // Second date value, pinned to right of cell and baseline of its label. 
     [self.dateTwoToValue mas_remakeConstraints:^(MASConstraintMaker *make) { 
      make.right.equalTo(self.dateOneValue); 
      make.baseline.equalTo(self.dateTwoToLabel); 
     }]; 

     self.didSetupConstraints = YES; 
    } 

    [super updateConstraints]; 
} 

- (void)uninstallMessageConstraints { 
    [self.pinBottomOfDateTwoLabelToBottomOfContentViewConstraint uninstall]; 
    for (MASConstraint *constraint in self.messageConstraints) { 
     [constraint uninstall]; 
    } 
    [self.contentView mas_remakeConstraints:^(MASConstraintMaker *make) { 
     self.pinBottomOfDateTwoLabelToBottomOfContentViewConstraint = make.bottom.equalTo(self.dateTwoToLabel).with.offset(14); 
    }]; 
} 

- (void)installMessageConstraints { 

    __weak typeof (self.contentView) contentView = self.contentView; 

    [self.pinBottomOfDateTwoLabelToBottomOfContentViewConstraint uninstall]; 

    // Below, add constraints of `self.messageConstraints` into an array so 
    // they can be removed later. 

    [self.messageConstraints addObjectsFromArray:[self.messageLabel mas_remakeConstraints:^(MASConstraintMaker *make) { 
     make.left.equalTo(self.dateOneLabel); 
     make.top.equalTo(self.dateTwoToLabel.mas_bottom).with.offset(6); 
    }]]; 

    self.messageConstraints = [[self.messageText mas_remakeConstraints:^(MASConstraintMaker *make) { 
     make.left.equalTo(self.messageLabel); 
     make.top.equalTo(self.messageLabel.mas_bottom).with.offset(6); 
     make.right.equalTo(contentView).with.offset(-14); 
    }] mutableCopy]; 

    [contentView mas_makeConstraints:^(MASConstraintMaker *make) { 
     self.pinBottomOfDateTwoLabelToBottomOfContentViewConstraint = make.bottom.equalTo(self.messageText).with.offset(14); 
    }]; 

} 


- (void)setModel:(MyModel *)model { 
    if (!model.message || model.message.length < 1) { 
     [self uninstallMessageConstraints]; 
     self.messageText.text = @""; 
     [self.messageLabel removeFromSuperview]; 
     [self.messageText removeFromSuperview]; 
    } else { 
     self.messageText.text = model.message; 
     if (![self.contentView.subviews containsObject:self.messageLabel]) { 
      [self.contentView addSubview:self.messageLabel]; 
     } 
     if (![self.contentView.subviews containsObject:self.messageText]) { 
      [self.contentView addSubview:self.messageText]; 
     } 
     [self installMessageConstraints]; 
    } 

    self.dateOneValue.text = model.dateOne; 
    self.dateTwoValue.text = model.dateTwo; 

    [self.contentView setNeedsDisplay]; 
    [self.contentView setNeedsLayout]; 
} 

@end 

Я мастерить с этим в течение двух дней, а в некоторых местах, это выглядело как хотелось бы, но с ошибками Autolayout. Я понятия не имею, где мои ошибки лежат, поэтому мой общий вопрос: что не так с моим кодом и что нужно изменить для получения правильного результата?

Большое спасибо.

+0

Каковы были «Ошибки автопотока»? – mackworth

+0

На основании приведенного выше кода ошибок нет, но визуальный внешний вид изображен так, как показано. – Bibs

+0

Не используете ли вы новые саморазмерные ячейки api по какой-то причине? Это делает это намного проще. – rdelmar

ответ

0

Я думаю, вам нужно добавить self.messageText.lineBreakMode = NSLineBreakByWordWrapping, чтобы заставить его несколько строк.

+0

По-прежнему остается проблема с левым полем от ярлыков до того, как край окна не применяется, поэтому я думаю, что здесь есть большая проблема. – Bibs

+0

FYI это не имело никакого эффекта. – Bibs

+0

Извините. Вы можете распечатать ограничения с помощью '[self constraintsAffectingLayoutForAxis: UILayoutConstraintAxisHorizontal];' посмотреть, что происходит – mackworth

Смежные вопросы