2013-09-23 8 views
29

Próbuję zaimplementować UITableView, który będzie zachowywać się podobnie do osi czasu klienta twitter. Teraz po prostu próbuję uzyskać dwie etykiety wewnątrz UITableViewCell. Zgodnie z poleceniem this Stack Overflow answer używam innego identyfikatora ponownego użycia dla każdego układu. Moje układy są proste, składają się z jednej etykiety lub dwóch etykiet. W końcu będę regulować wysokość UITableViewCells, ale najpierw muszę uzyskać komórki wypełnione treścią.Jak utworzyć niestandardowe UITableViewCell programowo za pomocą AutoLayout

Mogę wyświetlić etykiety tak, jeśli ustawię ich ramkę na initWithFrame:, ale ograniczenia nie są implementowane.

  • Pytanie: Co zapobiega pojawianiu się etykiet i ograniczeń? Wyraźnie brakuje mi czegoś w mojej implementacji UITableViewCell, ale nie mam pojęcia, co to jest.

  • Drugie pytanie: Czy prawidłowo rejestruję klasę UITableViewCell dla każdego ponownego użycia identyfikatora w viewDidLoad?

To może wydawać się trudne, ale twórca interfejsów myli mnie, chciałbym to wszystko zrobić w kodzie.

Oto kod dla zwyczaju UITableViewCell nazwie TVTCell.h:

static NSString * const kCellIDTitle = @"CellWithTitle"; 
static NSString * const kCellIDTitleMain = @"CellWithTitleMain"; 

@interface TVTCell : UITableViewCell 
{ 
    NSString *reuseID; 
} 

@property (nonatomic, strong) UILabel *nameLabel; 
@property (nonatomic, strong) UILabel *mainLabel; 

@end 

I TVTCell.m:

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

     nameLabel = [[UILabel alloc] init]; 
     [nameLabel setTextColor:[UIColor blackColor]]; 
     [nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]]; 
     [nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; 
     [nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.contentView addSubview:nameLabel]; 

     mainLabel = [[UILabel alloc] init]; 
     [mainLabel setTextColor:[UIColor blackColor]]; 
     [mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]]; 
     [mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; 
     [mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.contentView addSubview:mainLabel]; 

     [self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO]; 

    } 
    return self; 
} 


- (void)updateConstraints 
{ 
    [super updateConstraints]; 

    NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel); 
    if (reuseID == kCellIDTitle) { 
     NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" 
               options: NSLayoutFormatAlignAllCenterX 
               metrics:nil 
                views:views]; 
     [self.contentView addConstraints:constraints]; 
     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|" 
                   options: NSLayoutFormatAlignAllCenterX 
                   metrics:nil 
                   views:views]; 
     [self.contentView addConstraints:constraints]; 
    } 
    if (reuseID == kCellIDTitleMain) { 
     NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" 
                     options: NSLayoutFormatAlignAllCenterX 
                     metrics:nil 
                     views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mainLabel]|" 
                     options: NSLayoutFormatAlignAllCenterX 
                     metrics:nil 
                     views:views]; 
     [self.contentView addConstraints:constraints]; 

     constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel]|" 
                   options: NSLayoutFormatAlignAllLeft 
                   metrics:nil 
                   views:views]; 
     [self.contentView addConstraints:constraints]; 

     [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel 
            attribute:NSLayoutAttributeHeight 
            relatedBy:NSLayoutRelationEqual 
             toItem:nil 
            attribute:NSLayoutAttributeNotAnAttribute 
            multiplier:0.0 
             constant:44.0]]; 
     [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:nameLabel 
                    attribute:NSLayoutAttributeWidth 
                    relatedBy:NSLayoutRelationEqual 
                     toItem:self.contentView 
                    attribute:NSLayoutAttributeNotAnAttribute 
                    multiplier:0.0 
                     constant:1]]; 
    } 
} 

Niestety, mnóstwo kodu. Oto mój UITableView na tableView:cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.row == 0 || indexPath.row == 2 || indexPath.row == 3) { 
     TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitle forIndexPath:indexPath]; 

     [[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]]; 

     return cell; 
    } else if (indexPath.row == 1 || indexPath.row == 4 || indexPath.row == 5) { 
     TVTCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIDTitleMain forIndexPath:indexPath]; 

     [[cell nameLabel] setText:[nameArray objectAtIndex:indexPath.row]]; 
     [[cell mainLabel] setText:[dataArray objectAtIndex:indexPath.row]]; 

     return cell; 
    } else 
    { 
     UITableViewCell *badCell = [[UITableViewCell alloc] init]; 
     NSLog(@"Warning! returning a cell that shouldnt be here"); 
     badCell.textLabel.text = @"Warning!"; 
     return badCell; 
    } 
} 

I wreszcie, UITableView za viewDidLoad metoda:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    [[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitle]; 
    [[self tableView] registerClass:[TVTCell class] forCellReuseIdentifier:kCellIDTitleMain]; 
} 
+0

Znalazłem to samo zamieszanie. dzięki za twoje pytanie. – stackFish

Odpowiedz

31

Istnieje kilka rzeczy źle z kodem. Po pierwsze, myślę, że znajdziesz, jeśli zrobisz jakieś logowanie, że updateConstraints nigdy nie jest wywoływana. Wstawiłbym cały kod do metody init. Ponadto, w twoich ograniczeniach jest kilka błędów. Ograniczenie, w którym ustawiłeś wysokość na 44, nie jest potrzebne, ponieważ masz już przypięte etykiety do i do dolnej części komórki. Nie wiem, co próbujesz zrobić z tym ostatnim, wygląda na to, że nazwa LABEL 1 punkt byłaby szeroka. Ponadto, nie należy ustawiać translatesAutoresizingMaskIntoConstraints na NIE dla widoku treści, co powoduje dziwne efekty. Więc to jest kod Myślę, że chcesz:

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

     nameLabel = [[UILabel alloc] init]; 
     [nameLabel setTextColor:[UIColor blackColor]]; 
     [nameLabel setBackgroundColor:[UIColor colorWithHue:32 saturation:100 brightness:63 alpha:1]]; 
     [nameLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; 
     [nameLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.contentView addSubview:nameLabel]; 

     mainLabel = [[UILabel alloc] init]; 
     [mainLabel setTextColor:[UIColor blackColor]]; 
     [mainLabel setBackgroundColor:[UIColor colorWithHue:66 saturation:100 brightness:63 alpha:1]]; 
     [mainLabel setFont:[UIFont fontWithName:@"HelveticaNeue" size:18.0f]]; 
     [mainLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; 
     [self.contentView addSubview:mainLabel]; 

     NSDictionary *views = NSDictionaryOfVariableBindings(nameLabel, mainLabel); 
     if (reuseID == kCellIDTitle) { 
      NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" 
                      options: 0 
                      metrics:nil 
                      views:views]; 
      [self.contentView addConstraints:constraints]; 
      constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel]|" 
                    options: 0 
                    metrics:nil 
                    views:views]; 
      [self.contentView addConstraints:constraints]; 
     } 
     if (reuseID == kCellIDTitleMain) { 
      NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[nameLabel]|" 
                      options:0 
                      metrics:nil 
                      views:views]; 
      [self.contentView addConstraints:constraints]; 

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

      constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[nameLabel][mainLabel(==nameLabel)]|" 
                    options: 0 
                    metrics:nil 
                    views:views]; 
      [self.contentView addConstraints:constraints]; 

     } 
    } 
    return self; 
} 
+0

Cudownie, dziękuję za poprawienie mojego kodu. Komórki wyświetlają ładnie skalowane komórki z pojedynczą etykietą, aby dopasować je do domyślnej wysokości komórki równej 88,0, a komórki z podwójnym etykietowaniem dzielą tę przestrzeń równomiernie. W odpowiedzi na przepełnienie stosu, o której wspomniałem wcześniej, programista mówi: "Pozwól, aby wewnętrzny rozmiar treści tych podekcji powodował wzrost widoku zawartości komórki widoku tabeli, upewniając się, że opór kompresji zawartości i ograniczenia przyswajania zawartości w pionowym wymiarze dla każdego wydziału nie są nadpisywane przez dodane ograniczenia o wyższym priorytecie. "_ Jak i gdzie miałbym to zrobić? –

+0

@ShawnThroop, nie jestem pewien jak to by działało - sposób, w jaki używa się tego plakatu, to inne podejście niż to, z czego zwykle korzystam. Czy musisz mieć różne wysokości dla swoich komórek? Jeśli tak, to czy ta wysokość będzie zależeć tylko od liczby etykiet, czy też niektóre etykiety mają zmienną liczbę linii? – rdelmar

+0

Docelowo celuję w komórkę o wysokości zależnej głównie od liczby lub linii jednej etykiety. Muszę przeczytać więcej na temat odporności na kompresję treści i przytulania treści. Do Apple Docs ... btw, Jak normalnie byś to zrobił? Zgaduję, że to łatwiejsze, co próbuję zaimplementować. –

0

Można utworzyć UITableViewCell programowo w szybkim 4 za pomocą automatycznego układu jak poniżej.Nie jest to rozwiązanie Twojego problemu powyżej, jak określono w pytaniu, to jest bardziej ogólne realizacja jak stworzyć komórkę Tableview programowo w szybkich użyciu automatycznego układu:

class ViewController: UITableViewController { 

override func viewDidLoad() { 
    super.viewDidLoad() 
    tableView.register(CustomCell2.self, forCellReuseIdentifier: "cell") 
} 

override func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
} 
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return 2 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? CustomCell2 else { return UITableViewCell() } 
    cell.model = CellModel(labelString: "set constriant by code") 
    return cell 
    } 
    } 

Zdefiniuj Model:

struct CellModel { 
    let labelString : String 
} 

Definiowanie niestandardowe komórek:

class CustomCell2 : UITableViewCell { 
private let label : UILabel = { 
    let label = UILabel() 
    label.translatesAutoresizingMaskIntoConstraints = false // enable auto layout 
    label.backgroundColor = .green // to visualize the background of label 
    label.textAlignment = .center // center text alignment 
    return label 
}() 

private func addLabel() { 
    addSubview(label) 
    NSLayoutConstraint.activate([ 
     // label width is 70% of cell width 
     label.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.7), 
     // label is horizontally center of cell 
     label.centerXAnchor.constraint(equalTo: centerXAnchor) 
    ]) 
} 

var model : CellModel? { 
    didSet { 
     label.text = model?.labelString ?? "" 
    } 
} 

// Init 
override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 
    super.init(style: style, reuseIdentifier: reuseIdentifier) 
    addLabel() 
} 

required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
} 
} 

This is the output of above program.

This is the actual project, you can check out.