2013-08-20 15 views
5

Istnieje wiele dobrych informacji na temat SO i elsewhere dotyczących obliczania wymaganej wysokości wiersza UITableView w zależności od rozmiaru podglądu. Typowym przykładem, a tym, który tutaj aplikuję, jest komórka zawierająca etykietę z tekstem o zmiennej długości.Etykieta o zmiennej długości, wysokości rzędów widoku i automatyczny układ

enter image description here

Zazwyczaj rada jest użycie sizeWithFont:constrainedToSize:lineBreakMode: w tableview na heightForRowAtIndexPath:. Ale większość przykładów, które widziałem, używa "magicznej" liczby opartej na znanej szerokości etykiety.

CGSize constraint = CGSizeMake(224.0, MAXFLOAT); //224 is known to be the width available 
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping]; 

Niektóre lepsze przykłady mogą korzystać granic tableview, a następnie odjąć magicznych liczb lub stałe dla innych poglądów w komórce, która jest przynajmniej trochę jaśniejszy (i działa lepiej, jeżeli granice zmienić na obracanie itp) .

CGSize constraint = CGSizeMake(self.tableview.bounds.size.width - 20 - 10 - 36 - 20, MAXFLOAT); //each non-label width subtracted 
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping]; 

To jest wspólne podejście, ale wydaje się, że brakuje. Kto może powiedzieć, że szerokość pozostałych podpowierzchni komórek, a nawet czcionka, są gwarantowane, że się nie zmienią (lub czy zawsze zostaną starannie zmienione w obu miejscach)?

Zdecydowałem, że wolałbym, aby komórka była odpowiedzialna za zapewnienie tej wysokości. Komórka zawsze zna swoje atrybuty. Aby to osiągnąć, najpierw zrobiłem cały mój kod układu w komórce, odwołując się do lokalnych stałych. Następnie dodałem metodę klasy do mojej niestandardowej klasy komórki, która może zwrócić wymaganą wysokość dla dowolnego fragmentu tekstu, w oparciu o własne czcionki i stałe wymiarowania.

+ (CGFloat)heightRequiredForText:(NSString *)text usingWidth:(CGFloat)width 
{ 
    //a class method that tells the caller how much height is needed for the provided text, based on the cell's size and font constants 
    CGSize constraintSize = CGSizeMake(width - kMargin - kGap - kMargin - kCheckboxWidth, MAXFLOAT); 
    CGRect bounds = [text boundingRectWithSize:constraintSize 
               options:NSStringDrawingUsesLineFragmentOrigin 
              attributes:@{NSFontAttributeName:self.labelFont} 
               context:nil]; 
    return bounds.size.height; 
} 

Pozwala to UITableViewController po prostu dostarczyć tekst i szerokość obecne granice (czyli szerokość od tableview). Czcionkę i układ można zmienić w podklasie komórki, a wszystko dalej "po prostu działa".

Pytanie 1

Podobnie jak marginesie, jest to rozsądne? Czy istnieje lepszy sposób na osiągnięcie tego samego?

Pytanie 2

Oto główny problem mam z tym (i bardziej standardowe) podejście. Gdy komórka jest w trybie edycji, szerokość etykiety zmienia się, aby pomieścić akcesoria do edycji. Ponieważ wysokość wiersza jest stała, a etykieta korzysta z automatycznego układu, jego wysokość wzrasta.

enter image description here

Wymagane zachowanie jest wysokość etykiety pozostaje stała i obcięcie powinny być stosowane, gdy jest to konieczne.

Gdzie i jak mogę to wdrożyć? Czy powinienem coś zrobić w ustawianiu komórki? Może dodanie kolejnego ograniczenia w celu ograniczenia wysokości i włączenie obcinania, z przeciwną stosowaną podczas edycji == NIE? A co ze schematem "przeciągnij, aby usunąć" - myślę, że to nie wyzwala setEditing? A co z layoutSubview - czy mogę coś tam zrobić?

+0

Podejście polecam jest użycie [instancje komórkowych prototyp] (http://stackoverflow.com/questions/13660004/retrieve-custom -prototype-cell-height-from-storyboard/14127936 # 14127936) dla tego rodzaju rzeczy. –

Odpowiedz

1

Próbowałem wielu rzeczy - najbliższe było przesłonięcie layoutSubviews, testowanie, czy użytkownik przełączył się do trybu edycji, a jeśli tak, to przechwycenie wewnętrznej wysokości etykiety, a następnie dodanie tymczasowego ograniczenia w celu jej egzekwowania (co został usunięty po wyjściu z trybu edycji). Sprawdzało się dobrze, z wyjątkiem kilku skrajnych przypadków.

Ale potem zacząłem trochę myśleć o układzie automatycznym. Co starałem się osiągnąć? Nie chciałem, aby etykieta wzrosła, gdy jej szerokość się zmniejszyła. To dość proste ograniczenie:

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.label 
                    attribute:NSLayoutAttributeHeight 
                    relatedBy:NSLayoutRelationLessThanOrEqual 
                     toItem:self.contentView 
                    attribute:NSLayoutAttributeHeight 
                    multiplier:1 
                    constant:0]]; 

Dodanie tego dodatkowego ograniczenia działa dobrze. Należy zauważyć, że także przełączyć tryb linia przerwania obciąć na EDIT:

enter image description here

Powiązane problemy