2014-10-14 2 views
8

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

Я пытался создать на моей, и я знаю, что я далеко ..

#import "ViewController.h" 

    @interface ViewController() <UITableViewDataSource, UITableViewDelegate> 

    @property(strong, nonatomic) UITableView *tableView; 
    @property(strong, nonatomic) NSMutableArray *dataArray; 
    @property (strong, nonatomic) UITableViewCell *customCell; 

    @end 

    @implementation ViewController 

    - (void)viewDidLoad { 
     [super viewDidLoad]; 
     // Do any additional setup after loading the view, typically from a nib. 
     self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; 
     [self.tableView setDataSource:self]; 
     [self.tableView setDelegate:self]; 
     [self.tableView setShowsVerticalScrollIndicator:NO]; 
     self.tableView.translatesAutoresizingMaskIntoConstraints = NO; 
     self.tableView.rowHeight = UITableViewAutomaticDimension; 
     [self.view addSubview:self.tableView]; 

     self.dataArray = [@[@"For the past 33 years, I have looked in the mirror every morning and asked myself: 'If today were the last day of my life, would I want to do what I am about to do today?' And whenever the answer has been 'No' for too many days in a row, I know I need to change something. -Steve Jobs", 
         @"Be a yardstick of quality. Some people aren't used to an environment where excellence is expected. - Steve Jobs", 
         @"Innovation distinguishes between a leader and a follower. -Steve Jobs"] mutableCopy]; 


    } 

    - (void)didReceiveMemoryWarning { 
     [super didReceiveMemoryWarning]; 
     // Dispose of any resources that can be recreated. 
    } 

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 

     return [self.dataArray count]; 
    } 

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

     if (cell == nil) 
     { 
      cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
     } 

     cell.backgroundColor = [UIColor colorWithRed:249.0/255 green:237.0/255 blue:224.0/255 alpha:1.0]; 

     int dataIndex = (int) indexPath.row % [self.dataArray count]; 
     cell.textLabel.text = self.dataArray[dataIndex]; 
     cell.textLabel.numberOfLines = 0; 
     cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping; 

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

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]|" 
                   options: 0 
                   metrics:nil 
                   views:views]; 
     [cell.contentView addConstraints:constraints]; 

     return cell; 

    } 

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
     // Calculate a height based on a cell 
     if(!self.customCell) { 
      self.customCell = [self.tableView dequeueReusableCellWithIdentifier:@"CustomCell"]; 
     } 

     // Configure the cell 
     int dataIndex = (int) indexPath.row % [self.dataArray count]; 
     self.customCell.textLabel.text = self.dataArray[dataIndex]; 

     // auto layout 

     NSDictionary *views = @{@"label":self.customCell.textLabel}; 
     NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" 
                     options:0 
                     metrics:nil 
                     views:views]; 
     [self.customCell.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]|" 
                   options: 0 
                   metrics:nil 
                   views:views]; 
     [self.customCell.contentView addConstraints:constraints]; 

     // Layout the cell 

     [self.customCell layoutIfNeeded]; 

     // Get the height for the cell 

     CGFloat height = [self.customCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; 

     // Padding of 1 point (cell separator) 
     CGFloat separatorHeight = 1; 

     return height + separatorHeight; 
    } 

    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 

     return 140; 

    } 


    @end 
+0

проверить это -> http://www.appcoda.com/self-sizing-cells/ – Maverick

+0

, но это делается с помощью раскадровки нет? Я ищу один полностью программно. –

ответ

6

Так, пройдя через множество примеров, я, наконец, понял, что был неправ. Его одна из тех вещей, где одни недостающие строки испортили весь код. Для меня это было,

cell.bodyLabel.preferredMaxLayoutWidth = tableView.bounds.size.width; 

, который нам нужно добавить в метод heightForRowAtIndexPath или дает ТРУДНОСТИ ошибку.

Я получил решение благодаря одному из комментариев к удивительному ответу here. Хотя в примере кода, приведенном в ответе, строка выше приведена в функции cellForRowAtIndexPath вместо heightForRowAtIndexPath. Но мой код не мог работать именно так.

Итак, основной код,

// RJCell.h

#import <UIKit/UIKit.h> 

@interface RJTableViewCell : UITableViewCell 

@property (strong, nonatomic) UILabel *titleLabel; 
@property (strong, nonatomic) UILabel *bodyLabel; 

@end 

// RJCell.m

#import "RJTableViewCell.h" 

@interface RJTableViewCell() 

@property (nonatomic, assign) BOOL didSetupConstraints; 

@end 

@implementation RJTableViewCell 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code 

     self.titleLabel = [[UILabel alloc] init]; 
     [self.titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail]; 
     [self.titleLabel setNumberOfLines:1]; 
     [self.titleLabel setTextAlignment:NSTextAlignmentLeft]; 
     [self.titleLabel setTextColor:[UIColor blackColor]]; 
     [self.titleLabel setBackgroundColor:[UIColor clearColor]]; 
     [self.contentView addSubview:self.titleLabel]; 

     // Add this label to the button 
     self.bodyLabel = [[UILabel alloc] init]; 
     [self.bodyLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.bodyLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; 
     [self.bodyLabel setLineBreakMode:NSLineBreakByTruncatingTail]; 
     [self.bodyLabel setNumberOfLines:0]; 
     [self.bodyLabel setTextAlignment:NSTextAlignmentLeft]; 
     [self.bodyLabel setTextColor:[UIColor darkGrayColor]]; 
     [self.bodyLabel setBackgroundColor:[UIColor clearColor]]; 
     [self.contentView addSubview:self.bodyLabel]; 
    } 

    return self; 
} 

- (void)updateConstraints { 
    [super updateConstraints]; 

    if (self.didSetupConstraints) return; 

    // Get the views dictionary 
    NSDictionary *viewsDictionary = 
     @{ 
      @"titleLabel" : self.titleLabel, 
      @"bodyLabel" : self.bodyLabel 
     }; 

    NSString *format; 
    NSArray *constraintsArray; 

    //Create the constraints using the visual language format 
    format = @"V:|-10-[titleLabel]-10-[bodyLabel]-10-|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:viewsDictionary]; 
    [self.contentView addConstraints:constraintsArray]; 

    format = @"|-10-[titleLabel]-10-|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:viewsDictionary]; 
    [self.contentView addConstraints:constraintsArray]; 

    format = @"|-10-[bodyLabel]-10-|"; 
    constraintsArray = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:viewsDictionary]; 
    [self.contentView addConstraints:constraintsArray]; 

    self.didSetupConstraints = YES; 
} 

@end 

// RJTableViewController.h

#import <UIKit/UIKit.h> 

@interface RJTableViewController : UITableViewController 

@end 

// RJTableViewController.m

#import "RJTableViewController.h" 
#import "RJTableViewCell.h" 

static NSString *CellIdentifier = @"CellIdentifier"; 

@interface RJTableViewController() 

@property(strong,nonatomic) NSMutableArray *titleArray; 
@property(strong,nonatomic) NSMutableArray *bodyArray; 

@end 

@implementation RJTableViewController 

- (id)initWithStyle:(UITableViewStyle)style 
{ 
    self = [super initWithStyle:style]; 
    if (self) { 
     // Custom initialization 
     self.title = @"Table View Controller"; 
    } 
    return self; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [self.tableView registerClass:[RJTableViewCell class] forCellReuseIdentifier:CellIdentifier]; 
    self.titleArray = [[UIFont familyNames] mutableCopy]; 
    for(int i = 0; i < 100; i++) { 
     [self.titleArray addObjectsFromArray:[UIFont familyNames]]; 
    } 
    self.bodyArray = [@[@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",@"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",@"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",@"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."] mutableCopy]; 
} 

- (void)contentSizeCategoryChanged:(NSNotification *)notification 
{ 
    [self.tableView reloadData]; 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    // Return the number of sections. 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    // Return the number of rows in the section. 
    return [self.titleArray count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

    RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    int dataIndex = (int) indexPath.row % [self.bodyArray count]; 
    cell.titleLabel.text = self.titleArray[indexPath.row]; 
    cell.bodyLabel.text = self.bodyArray[dataIndex]; 

    // Make sure the constraints have been added to this cell, since it may have just been created from scratch 
    [cell setNeedsUpdateConstraints]; 

    return cell; 
} 

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 

    RJTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    int dataIndex = (int) indexPath.row % [self.bodyArray count]; 
    cell.titleLabel.text = self.titleArray[indexPath.row]; 
    cell.bodyLabel.text = self.bodyArray[dataIndex]; 

    cell.bodyLabel.preferredMaxLayoutWidth = tableView.bounds.size.width - (20.0 * 2.0f); 

    [cell setNeedsUpdateConstraints]; 
    [cell updateConstraintsIfNeeded]; 
    [cell.contentView setNeedsLayout]; 

    [cell.contentView layoutIfNeeded]; 

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

    return height; 
} 

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return 200.0f; 
} 

@end 

В принципе, сложная часть находится в двух местах, сначала устанавливая ограничения. Во-вторых, реализация методов heightForRowAtIndexPath и cellForRowAtIndexPath.

+0

Есть ли причина, по которой вы не применяете источники данных и делегировать протоколы в своем коде решения? –

+0

Извините за поздний ответ, но я думаю, что я внедрил все минимально необходимый код. Существует cellForRowAtIndexPath для источника данных. Конечно, я не принял никакого отдельного делегата datasource, но это потому, что я хотел сохранить его простым и с минимальным необходимо код .. –

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