Zunächst ist es sehr wichtig zu beachten, dass es einen großen Unterschied zwischen UITextView und UILabel gibt, wenn es darum geht, wie Text gerendert wird. UITextView verfügt nicht nur über Einfügungen an allen Rändern, sondern auch ein etwas anderes Textlayout.
Daher sizeWithFont:
ist UITextViews ein schlechter Weg.
Stattdessen hat UITextView
selbst eine Funktion aufgerufen, sizeThatFits:
die die kleinste Größe zurückgibt, die erforderlich ist, um den gesamten Inhalt UITextView
eines Begrenzungsrahmens anzuzeigen , den Sie angeben können.
Das Folgende funktioniert sowohl für iOS 7 als auch für ältere Versionen gleichermaßen und enthält derzeit keine veralteten Methoden.
Einfache Lösung
- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
UITextView *calculationView = [[UITextView alloc] init];
[calculationView setAttributedText:text];
CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
Diese Funktion nimmt a NSAttributedString
und die gewünschte Breite als CGFloat
und gibt die benötigte Höhe zurück
Detaillierte Lösung
Da ich kürzlich etwas Ähnliches getan habe, dachte ich, ich würde auch einige Lösungen für die damit verbundenen Probleme teilen, auf die ich gestoßen bin. Ich hoffe es wird jemandem helfen.
Dies ist weitaus ausführlicher und wird Folgendes abdecken:
- Natürlich: Festlegen der Höhe von a
UITableViewCell
basierend auf der Größe, die zum Anzeigen des vollständigen Inhalts eines enthaltenen Inhalts erforderlich istUITextView
- Reagieren Sie auf Textänderungen (und animieren Sie die Höhenänderungen der Zeile).
- Halten Sie den Cursor im sichtbaren Bereich und halten Sie den Ersthelfer
UITextView
beim Ändern der Größe UITableViewCell
während der Bearbeitung auf
Wenn Sie mit einer statischen Tabellenansicht arbeiten oder nur eine bekannte Anzahl von UITextView
s haben, können Sie Schritt 2 möglicherweise viel einfacher gestalten.
1. Überschreiben Sie zunächst den heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// check here, if it is one of the cells, that needs to be resized
// to the size of the contained UITextView
if ( )
return [self textViewHeightForRowAtIndexPath:indexPath];
else
// return your normal height here:
return 100.0;
}
2. Definieren Sie die Funktion, die die benötigte Höhe berechnet hat:
Fügen Sie Ihrer Unterklasse eine NSMutableDictionary
(in diesem Beispiel als textViews
) Instanzvariable hinzu UITableViewController
.
Verwenden Sie dieses Wörterbuch, um Verweise auf die Person UITextViews
wie folgt zu speichern :
(und ja, indexPaths sind gültige Schlüssel für Wörterbücher )
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Do you cell configuring ...
[textViews setObject:cell.textView forKey:indexPath];
[cell.textView setDelegate: self]; // Needed for step 3
return cell;
}
Diese Funktion berechnet nun die tatsächliche Höhe:
- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
UITextView *calculationView = [textViews objectForKey: indexPath];
CGFloat textViewWidth = calculationView.frame.size.width;
if (!calculationView.attributedText) {
// This will be needed on load, when the text view is not inited yet
calculationView = [[UITextView alloc] init];
calculationView.attributedText = // get the text from your datasource add attributes and insert here
textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
}
CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
return size.height;
}
3. Aktivieren Sie die Größenänderung während der Bearbeitung
Für die nächsten beiden Funktionen ist es wichtig, dass der Delegat von UITextViews
auf Ihren eingestellt ist UITableViewController
. Wenn Sie als Delegat etwas anderes benötigen, können Sie dies umgehen, indem Sie die entsprechenden Anrufe von dort aus tätigen oder die entsprechenden NSNotificationCenter-Hooks verwenden.
- (void)textViewDidChange:(UITextView *)textView {
[self.tableView beginUpdates]; // This will cause an animated update of
[self.tableView endUpdates]; // the height of your UITableViewCell
// If the UITextView is not automatically resized (e.g. through autolayout
// constraints), resize it here
[self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}
4. Folgen Sie dem Cursor beim Bearbeiten
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Dadurch wird der UITableView
Bildlauf zur Position des Cursors ausgeführt, wenn er sich nicht im sichtbaren Bereich der UITableView befindet:
- (void)scrollToCursorForTextView: (UITextView*)textView {
CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];
cursorRect = [self.tableView convertRect:cursorRect fromView:textView];
if (![self rectVisible:cursorRect]) {
cursorRect.size.height += 8; // To add some space underneath the cursor
[self.tableView scrollRectToVisible:cursorRect animated:YES];
}
}
5. Stellen Sie das sichtbare Rechteck ein, indem Sie Einsätze einstellen
Während der Bearbeitung können Teile von Ihnen UITableView
von der Tastatur abgedeckt werden. Wenn die Tabellenansichten nicht angepasst sind, scrollToCursorForTextView:
kann nicht zum Cursor gescrollt werden, wenn er sich am unteren Rand der Tabellenansicht befindet.
- (void)keyboardWillShow:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.35];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
[UIView commitAnimations];
}
Und letzter Teil:
Melden Sie sich in Ihrer Ansicht, die geladen wurde, für die Benachrichtigungen für Tastaturänderungen an über NSNotificationCenter
:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Bitte sei nicht böse auf mich, weil ich diese Antwort so lange gemacht habe. Obwohl nicht alles zur Beantwortung der Frage benötigt wird, glaube ich, dass es andere Menschen gibt, denen diese direkt verwandten Themen hilfreich sein werden.
AKTUALISIEREN:
Wie Dave Haupert betonte, habe ich vergessen, die rectVisible
Funktion aufzunehmen:
- (BOOL)rectVisible: (CGRect)rect {
CGRect visibleRect;
visibleRect.origin = self.tableView.contentOffset;
visibleRect.origin.y += self.tableView.contentInset.top;
visibleRect.size = self.tableView.bounds.size;
visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
return CGRectContainsRect(visibleRect, rect);
}
Ich bemerkte auch, dass dies scrollToCursorForTextView:
immer noch einen direkten Verweis auf eines der TextFields in meinem Projekt enthielt. Wenn Sie ein Problem damit haben, bodyTextView
nicht gefunden zu werden, überprüfen Sie die aktualisierte Version der Funktion.
attributedText
ohne Angabe von Schriftart, Farbe und Textausrichtung zum Festlegen von Standardwerten für NSAttributedString-Attribute für die Textansicht führt. In meinem Fall werden unterschiedliche Höhen der Textansicht für denselben Text angezeigt.Es gibt eine neue Funktion zum Ersetzen von sizeWithFont, die boundingRectWithSize ist.
Ich habe meinem Projekt die folgende Funktion hinzugefügt, die die neue Funktion unter iOS7 und die alte unter iOS unter 7 verwendet. Sie hat im Grunde die gleiche Syntax wie sizeWithFont:
Sie können IOS_NEWER_OR_EQUAL_TO_7 in Ihrer Datei prefix.pch in Ihrem Projekt wie folgt hinzufügen:
quelle
Wenn Sie UITableViewAutomaticDimension verwenden, habe ich eine wirklich einfache Lösung (nur iOS 8). In meinem Fall ist es eine statische Tabellenansicht, aber ich denke, Sie könnten dies für dynamische Prototypen anpassen ...
Ich habe einen Einschränkungsausgang für die Höhe der Textansicht und habe die folgenden Methoden wie folgt implementiert:
Denken Sie jedoch daran : Die Textansicht muss scrollbar sein, und Sie müssen Ihre Einschränkungen so einrichten, dass sie für die automatische Bemaßung funktionieren:
Das grundlegendste Zellenbeispiel ist:
quelle
Tim Bodeits Antwort ist großartig. Ich habe den Code von Simple Solution verwendet, um die Höhe der Textansicht korrekt zu ermitteln und diese Höhe in zu verwenden
heightForRowAtIndexPath
. Aber ich verwende den Rest der Antwort nicht, um die Größe der Textansicht zu ändern. Stattdessen schreibe ich Code, um dieframe
Textansicht in zu änderncellForRowAtIndexPath
.In iOS 6 und darunter funktioniert alles, aber in iOS 7 kann der Text in der Textansicht nicht vollständig angezeigt werden, obwohl die
frame
Größe der Textansicht tatsächlich geändert wurde. (Ich benutze nichtAuto Layout
). Es sollte der Grund sein, dass es in iOS 7 gibtTextKit
und die Position des Textes vonNSTextContainer
in gesteuert wirdUITextView
. In meinem Fall muss ich also eine Zeile hinzufügen, um diesomeTextView
festzulegen, damit sie in iOS 7 ordnungsgemäß funktioniert.Wie in der Dokumentation angegeben, bewirkt diese Eigenschaft Folgendes:
Wenn Sie den Standardwert beibehalten, wird nach dem Ändern der Größe
frame
vonsomeTextView
die Größe destextContainer
nicht geändert, was dazu führt, dass der Text nur in dem Bereich angezeigt werden kann, bevor die Größe geändert wird.Und vielleicht muss das für den
scrollEnabled = NO
Fall festgelegt werden, dass es mehr als einen gibttextContainer
, damit der Text von einemtextContainer
zum anderen zurückfließt .quelle
Hier ist eine weitere Lösung, die auf Einfachheit und schnelles Prototyping abzielt :
Konfiguration:
UITextView
mit anderen Inhalten.TableCell.h
.UITableView
ist verbunden mitTableViewController.h
.Lösung:
(1) Hinzufügen zu
TableViewController.m
:(2) Hinzufügen zu
TableCell.m
:Erläuterung:
Hier passiert also Folgendes: Jede Textansicht ist durch vertikale und horizontale Einschränkungen an die Höhe der Tabellenzellen gebunden. Wenn also die Höhe der Tabellenzellen zunimmt, vergrößert sich auch die Textansicht. Ich habe eine modifizierte Version des Codes von @ manecosta verwendet, um die erforderliche Höhe einer Textansicht zu berechnen, die zum angegebenen Text in eine Zelle passt. Das bedeutet, dass bei einem Text mit einer X-Anzahl von Zeichen
frameForText:
eine Größe zurückgegeben wird, deren Eigenschaftsize.height
der erforderlichen Höhe der Textansicht entspricht.Jetzt müssen Sie nur noch die Höhe der Zelle aktualisieren, um sie an die Höhe der erforderlichen Textansicht anzupassen. Und das wird erreicht bei
heightForRowAtIndexPath:
. Wie in den Kommentaren erwähnt,size.height
sollte nur ein Versatz hinzugefügt werden , da nur die Höhe für die Textansicht und nicht die gesamte Zelle angegeben ist. Im Beispiel betrug dieser Wert 80.quelle
dream.dream
war der Text, den ich in der Textansicht gerendert habe.Ein Ansatz, wenn Sie Autolayout verwenden, besteht darin, die Autolayout-Engine die Größe für Sie berechnen zu lassen. Dies ist nicht der effizienteste Ansatz, aber ziemlich praktisch (und wohl der genaueste). Mit zunehmender Komplexität des Zellenlayouts wird es bequemer - z. B. haben Sie plötzlich zwei oder mehr Textansichten / Felder in der Zelle.
Ich beantwortete eine ähnliche Frage mit einem vollständigen Beispiel für die Dimensionierung von Tabellenansichtszellen mithilfe des automatischen Layouts hier:
Wie kann ich die Größe der Übersicht ändern, um sie an alle Unteransichten mit Autolayout anzupassen?
quelle
Die vollständige glatte Lösung ist wie folgt.
Zuerst benötigen wir die Zellenklasse mit einer Textansicht
Als nächstes verwenden wir es im TableViewController
Hier
minLines
können Sie die Mindesthöhe für die Textansicht festlegen (um der Höhenminimierung durch AutoLayout mit UITableViewAutomaticDimension zu widerstehen).moveRowAtIndexPath:indexPath:
Mit demselben IndexPath wird die Neuberechnung und das Layout der tableViewCell-Höhe gestartet.performWithoutAnimation:
Entfernt Nebeneffekte (TableView-Inhaltsoffset springt beim Starten einer neuen Zeile während der Eingabe).Es ist wichtig,
relativeFrameOriginY
(nichtcontentOffsetY
!) Während dercontentSize
Zellenaktualisierung beizubehalten, da die Zellen, bevor die aktuelle Zelle auf unerwartete Weise durch AutoLayout-Berechnung geändert werden kann. Es entfernt visuelle Sprünge bei der Silbentrennung des Systems, während lange Wörter eingegeben werden.Beachten Sie, dass Sie die Eigenschaft nicht festlegen sollten
estimatedRowHeight
! Folgendes funktioniert nichtVerwenden Sie nur die tableViewDelegate-Methode.
================================================== ========================
Wenn es Ihnen nichts ausmacht, eine schwache Bindung zwischen tableView und tableViewCell zu verhindern und die Geometrie der tableView von tableViewCell aus zu aktualisieren , können Sie die obige
TextInputTableViewCell
Klasse aktualisieren :quelle
Die Höhe Ihrer Zelle wird anhand des Inhalts von UILabel berechnet, der gesamte Text wird jedoch von TextField angezeigt.
quelle
Ich denke, auf diese Weise können Sie die Höhe Ihrer Textansicht zählen und dann die Größe Ihrer Tabellenansichtszelle entsprechend dieser Höhe ändern, sodass Sie den vollständigen Text in der Zelle anzeigen können
quelle
Schnelle Version
quelle
Wenn Sie die
UITableViewCell
Höhe automatisch an die Höhe der innerenUITextView
Höhe anpassen möchten . Siehe meine Antwort hier: https://stackoverflow.com/a/45890087/1245231Die Lösung ist ganz einfach und sollte sicher seit iOS 7. funktioniert , dass die
Scrolling Enabled
Option aktiviert ist ausgeschaltet für dieUITextView
innerhalb derUITableViewCell
im Storyboard.Dann setzen Sie in viewDidLoad () Ihres UITableViewControllers das
tableView.rowHeight = UITableViewAutomaticDimension
undtableView.estimatedRowHeight > 0
wie:Das ist es.
UITableViewCell
Die Höhe wird automatisch an dieUITextView
Höhe des Innenraums angepasst .quelle
Für iOS 8 und höher können Sie einfach verwenden
your_tablview.estimatedrowheight= minheight
Sie wollenquelle