2009-08-30 7 views
14

Posiadam kilka UITableViewCells, które muszą zmienić ich wysokość w zależności od długości napisów w środku. Obliczam niezbędną wysokość wewnątrz tableView:cellForRowAtIndexPath:, a następnie zapisuję ją w zmiennej (self.specialRowHeight). Wtedy mam:Pobierz tableView: heightForRowAtIndexPath: stanie się po tableView: cellForRowAtIndexPath :?

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
    if (indexPath.section == SPECIAL_SECTION) { 
     return self.specialRowHeight; 
    } 
    else { 
     return 44; 
    } 
} 

Tyle że wydaje się być coraz wezwany przed tableView:cellForRowAtIndexPath: bit, dlatego zawsze zero.

Czy istnieje sposób obejścia tego, a może inny sposób to zrobić?

Dzięki!

Odpowiedz

11

Zamierzam odpowiedzieć na moje własne pytanie tutaj:

Początkowo byłem dość pewny, że obliczenia wysokości były przywiązane do metody tableView:cellForRowAtIndexPath:, i nie może być przeniesiony gdzie indziej. Jednak dzięki kilku restrukturyzacjom udało mi się wydobyć te rzeczy i wprowadzić je do tableView:heightForRowAtIndexPath:, co rozwiązuje wszystko.

Dla każdego, kto stara się uzyskać komórki auto-wysokość dostosowana do pracy, tu jest jakiś kod, który może pomóc:

// Inside tableView:cellForRowAtIndexPath: 
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap; 
cell.textLabel.numberOfLines = self.numberOfTextRows; 
// numberOfTextRows is an integer, declared in the class 

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

    CGSize theSize = [theObject.theStringToDisplay sizeWithFont:[UIFont systemFontOfSize:18.0f] constrainedToSize:CGSizeMake(265.0f, 9999.0f) lineBreakMode:UILineBreakModeWordWrap]; 
    // This gets the size of the rectangle needed to draw a multi-line string 
    self.numberOfTextRows = round(theSize.height/18); 
    // 18 is the size of the font used in the text label 
    // This will give us the number of lines in the multi-line string 

    if ((indexPath.section == FIXED_HEIGHT_SECTION) || (self.numberOfTextRows < 2)) { 
     return 44; 
     // 44 is the default row height; use it for empty or one-line cells (or in other table sections) 
    } else { 
     return theSize.height + 16; 
     // 16 seems to provide a decent space above/below; tweak to taste 
    } 
} 

Jeśli można myśleć o bardziej dokładny sposób obliczyć prawidłową wysokość komórek, Zamieniam się w słuch. :)

+0

Nie jestem pewien, dlaczego dzielisz prostą wysokość o 18, a następnie powtarzasz ją ponownie, ale poza tym robię to prawie w ten sam sposób. –

+0

Cóż, pierwszym działem jest sprawdzenie, ile rzędów jest potrzebnych, aby można było poprawnie ustawić 'cell.textLabel.numberOfLines'; jeśli tego nie ustawię, wszystko zostanie wydrukowane w jednej linii. Ale tak, myślę, że mógłbym użyć 'theSize.height' w tym ostatnim miejscu, zamiast' self.numberOfTextRows'. – Triz

+0

Edytował odpowiedź dla jasności i uproszczenia. Działa teraz naprawdę dobrze. – Triz

0

Możesz ustawić self.numberOfLines na 0 raz i będzie działać tak samo. (Jeśli numberOfLines jest ustawiony na 0, wówczas etykieta wykorzystuje tyle wierszy, ile potrzeba).

+0

Um ... numberOfTextRows jest niestandardową właściwością klasy, więc nie zrobi niczego poza tym, co mu powiem. Czy myślisz o cell.textLabel.numberOfLines? – Triz

+0

W każdym razie, tak, można ustawić 'cell.textLabel.numberOfLines' na' 0', ale nadal przydatne jest ustalenie rzeczywistej liczby, która będzie używana (do obliczenia odpowiedniej wysokości wiersza, jak na przykład tutaj) . Uważam, że wynikowy kod jest znacznie bardziej przejrzysty, ponieważ "0" nie jest w ogóle semantycznie pomocny na pierwszy rzut oka. – Triz

-7

Moje rozwiązanie było nazwać tableView:cellForRowAtIndexPath: wewnątrz realizacji tableView:heightForRowAtIndexPath: następująco

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

    [self tableView:aTableView cellForRowAtIndexPath:indexPath]; 
    return headerHeight; 
} 
+3

'tableView: heightForRowAtIndexPath:' jest wywoływana dla każdego (!) Pojedynczego wiersza w tableView. Z tego powodu nie należy używać drogich połączeń, takich jak 'tableView: cellForRowAtIndexPath:'. –

+0

Nie wiem, dlaczego ten głos został odrzucony, ponieważ ta metoda pozwala przetestować rzeczywistą wysokość komórki, nawet jeśli etykieta nie jest jedyną zawartością. Jest to jednak bardzo kosztowne. – Kyle

Powiązane problemy