Jak zawijać tekst w UITableViewCell bez komórki niestandardowej

151

To jest na iPhonie 0S 2.0. Odpowiedzi na 2.1 też są w porządku, chociaż nie znam żadnych różnic dotyczących tabel.

Wydaje się, że powinno być możliwe zawijanie tekstu bez tworzenia niestandardowej komórki, ponieważ domyślnie UITableViewCellzawiera UILabel. Wiem, że mogę sprawić, że zadziała, jeśli utworzę niestandardową komórkę, ale nie o to próbuję - chcę zrozumieć, dlaczego moje obecne podejście nie działa.

Dowiedziałem się, że etykieta jest tworzona na żądanie (ponieważ komórka obsługuje dostęp do tekstu i obrazu, więc nie tworzy widoku danych, dopóki nie jest to konieczne), więc jeśli zrobię coś takiego:

cell.text = @""; // create the label
UILabel* label = (UILabel*)[[cell.contentView subviews] objectAtIndex:0];

wtedy otrzymuję prawidłową etykietę, ale ustawienie numberOfLinesna niej (i lineBreakMode) nie działa - nadal otrzymuję tekst jednowierszowy. W UILabeltekście jest dużo wysokości do wyświetlenia - zwracam tylko dużą wartość wysokości w heightForRowAtIndexPath.

Airsource Ltd
źródło

Odpowiedzi:

277

Oto prostszy sposób i działa dla mnie:

Wewnątrz twojej cellForRowAtIndexPath:funkcji. Podczas pierwszego tworzenia komórki:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}

Zauważysz, że ustawiłem liczbę linii dla etykiety na 0. Dzięki temu może użyć tylu wierszy, ile potrzebuje.

Następna część to określenie, jak duża UITableViewCellbędzie twoja wola, więc zrób to w swojej heightForRowAtIndexPathfunkcji:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = @"Go get some text for your cell.";
    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];
    CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + 20;
}

Dodałem 20 do mojej zwróconej wysokości komórki, ponieważ podoba mi się mały bufor wokół mojego tekstu.

Tim Rupe
źródło
17
Nie musisz ustawiać wartości cell.textLabel.numberOfLines na jakąś arbitralnie wysoką liczbę. Ustawienie wartości 0 oznacza „tyle wierszy, ile potrzeba do wyświetlenia”.
mmc
Dzięki, wyedytuję mój post dzisiaj wieczorem, gdy będę miał szansę zweryfikować go we własnym projekcie.
Tim Rupe
1
Ustawienie liczby linii na 0 działa dobrze (tyle linii, ile potrzeba do wyświetlenia)
prakash
1
cagreen: Okazuje się, że mogę to powtórzyć, ale tylko wtedy, gdy używam iPhone OS 3.0 w symulatorze. Kiedy używam wersji 3.1+, zmiana rozmiaru elementu detailTextLabel pasuje do rozmiaru sizeWithFont. Tak więc metoda Tima działa naprawdę dobrze - tylko dla wersji 3.1+ (prawdopodobnie z powodu błędu / nieprawidłowości w domyślnym renderowaniu komórek 3.0). Dla przypomnienia, używam pionowego górnego / dolnego marginesu 12 (każdy), szczegółowego rozmiaru etykiety tekstowej (188.0, CGFLOAT_MAX) i pogrubionegoSystemFontOfSize 15.
Joe D'Andrea
17
UILineBreakModeWordWrap jest przestarzała w iOS 6. Zamiast tego użyj NSLineBreakByWordWrapping.
Ethan Allen,
16

Zaktualizowana odpowiedź Tima Rupe na iOS7:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = @"Go get some text for your cell.";
    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];

    NSAttributedString *attributedText =
        [[NSAttributedString alloc]
            initWithString:cellText
            attributes:@
            {
                NSFontAttributeName: cellFont
            }];
    CGRect rect = [attributedText boundingRectWithSize:CGSizeMake(tableView.bounds.size.width, CGFLOAT_MAX)
                                               options:NSStringDrawingUsesLineFragmentOrigin
                                               context:nil];
    return rect.size.height + 20;
}
ddiego
źródło
3

Krótki komentarz / odpowiedź, aby nagrać moje doświadczenie, gdy miałem ten sam problem. Pomimo korzystania z przykładów kodu wysokość komórki widoku tabeli się dostosowywała, ale etykieta wewnątrz komórki nadal nie dostosowywała się poprawnie - rozwiązaniem było ładowanie komórki z niestandardowego pliku NIB, co dzieje się po dostosowaniu wysokości komórki.

Miałem swoje ustawienia wewnątrz pliku NIB, aby nie zawijać tekstu i miałem tylko 1 wiersz na etykietę; ustawienia pliku NIB zastępowały ustawienia, które dostosowałem w kodzie.

Lekcja, którą wziąłem, polegała na tym, aby zawsze pamiętać o stanie obiektów w każdym momencie - być może nie zostały jeszcze utworzone! ... ktoś na kolejce.

Richard Le Mesurier
źródło
2

Jeśli mamy dodać tylko tekst w UITableViewkomórce, potrzebujemy tylko dwóch delegatów do pracy (nie ma potrzeby dodawania dodatkowych UILabels)

1) cellForRowAtIndexPath

2) heightForRowAtIndexPath

To rozwiązanie zadziałało dla mnie: -

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

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

    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;

    [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; 
    cell.textLabel.text = [mutArr objectAtIndex:indexPath.section];
    NSLog(@"%@",cell.textLabel.text);

    cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrow.png" ]];

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{  
    CGSize labelSize = CGSizeMake(200.0, 20.0);

    NSString *strTemp = [mutArr objectAtIndex:indexPath.section];

    if ([strTemp length] > 0)
        labelSize = [strTemp sizeWithFont: [UIFont boldSystemFontOfSize: 14.0] constrainedToSize: CGSizeMake(labelSize.width, 1000) lineBreakMode: UILineBreakModeWordWrap];

    return (labelSize.height + 10);
}

Tutaj ciąg mutArrjest zmienną tablicą, z której pobieram dane.

EDYCJA: - Oto tablica, którą wziąłem.

mutArr= [[NSMutableArray alloc] init];

[mutArr addObject:@"HEMAN"];
[mutArr addObject:@"SUPERMAN"];
[mutArr addObject:@"Is SUPERMAN powerful than HEMAN"];
[mutArr addObject:@"Well, if HEMAN is weaker than SUPERMAN, both are friends and we will never get to know who is more powerful than whom because they will never have a fight among them"];
[mutArr addObject:@"Where are BATMAN and SPIDERMAN"];
Arshad Parwez
źródło
2

Teraz widoki tabeli mogą mieć komórki o rozmiarze samoczynnym. Ustaw widok tabeli w następujący sposób

tableView.estimatedRowHeight = 85.0 //use an appropriate estimate tableView.rowHeight = UITableViewAutomaticDimension

Referencje Apple

Jason
źródło
0

Używam następujących rozwiązań.

Dane są podawane osobno w ramach członka:

-(NSString *)getHeaderData:(int)theSection {
    ...
    return rowText;
}

Obsługa może być łatwo wykonana cellForRowAtIndexPath. Zdefiniuj komórkę / zdefiniuj czcionkę i przypisz te wartości do wynikowej „komórki”. Zauważ, że numberoflinesjest ustawione na „0”, co oznacza, że ​​bierzesz to, co jest potrzebne.

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

    UIFont *cellFont = [UIFont fontWithName:@"Verdana" size:12.0];
    cell.textLabel.text= [self getRowData:indexPath.section];
    cell.textLabel.font = cellFont;
    cell.textLabel.numberOfLines=0;
    return cell;
}

W programie heightForRowAtIndexPathobliczam wysokość zawiniętego tekstu. Rozmiar boding powinien być powiązany z szerokością twojej komórki. Dla iPada powinno to być 1024. Dla iPhone i iPod 320.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIFont *cellFont = [UIFont fontWithName:@"Verdana" size:12.0];
    CGSize boundingSize = CGSizeMake(1024, CGFLOAT_MAX);
    CGSize requiredSize = [[self getRowData:indexPath.section] sizeWithFont:cellFont constrainedToSize:boundingSize lineBreakMode:UILineBreakModeWordWrap];
    return requiredSize.height;    
}
Vincent
źródło
0

Okazało się, że jest to dość proste i jednoznaczne:

[self.tableView setRowHeight:whatEvereight.0f];

na przykład:

[self.tableView setRowHeight:80.0f];

Może to być najlepsze / standardowe podejście, ale w moim przypadku zadziałało.

Manish Kr. Shukla
źródło
Jak rozumiem, właściwość rowHeight ustawia stałą wysokość, która będzie używana dla wszystkich komórek w widoku tabeli. Używanie rowHeight jest lepsze dla wydajności w dużych tabelach, ale jeśli potrzebujesz, aby wysokość każdej komórki różniła się w zależności od jej zawartości, wydaje się, że należy użyć metody tableView: heightForRowAtIndexPath:.
jk7
0

Wypróbuj mój kod szybko. Ten kod będzie działał również dla zwykłych etykiet UIL.

extension UILabel {
    func lblFunction() {
        //You can pass here all UILabel properties like Font, colour etc....
        numberOfLines = 0
        lineBreakMode = .byWordWrapping//If you want word wraping
        lineBreakMode = .byCharWrapping//If you want character wraping
    }
}

Teraz dzwoń po prostu w ten sposób

cell.textLabel.lblFunction()//Replace your label name 
iOS
źródło
-1

Myślę, że to lepsze i krótsze rozwiązanie. Po prostu sformatuj UILabel( textLabel) komórki, aby automatycznie obliczyć wysokość, określając ją sizeToFiti wszystko powinno być w porządku.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    cell.textLabel.text = @"Whatever text you want to put here is ok";
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    [cell.textLabel sizeToFit];

    return cell;
}
dukz
źródło
-2

Nie sądzę, aby można było w tym celu manipulować UITableViewCell'sprywatną bazą UILabel. Można dodać nowy UILabeldo celi siebie i skorzystać numberOfLinesz sizeToFitwielkości to w odpowiedni sposób. Coś jak:

UILabel* label = [[UILabel alloc] initWithFrame:cell.frame];
label.numberOfLines = <...an appriate number of lines...>
label.text = <...your text...>
[label sizeToFit];
[cell addSubview:label];
[label release];
drewh
źródło