Tout d'abord, il est très important de noter, qu'il y a une grande différence entre UITextView et UILabel quand il s'agit de la façon dont le texte est rendu. Non seulement UITextView ont encarts sur toutes les frontières, mais aussi la mise en forme de texte à l'intérieur, il est légèrement différent.
Par conséquent, sizeWithFont:
est une mauvaise manière de faire pour UITextViews.
Au lieu de cela UITextView
lui-même a une fonction appelée sizeThatFits:
qui sera de retour le plus petit de la taille nécessaire pour afficher tout le contenu de l' UITextView
à l'intérieur d'une zone de délimitation, que vous pouvez spécifier.
Ce qui suit fonctionnera aussi pour les deux iOS 7 et les versions plus anciennes et de plein droit maintenant, ne pas inclure toutes les méthodes, qui sont désormais obsolètes.
La Solution La Plus Simple
- (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;
}
Cette fonction prend un NSAttributedString
et la largeur souhaitée en tant que CGFloat
et le retour de la hauteur nécessaire
Une Solution Détaillée
Depuis que j'ai récemment fait quelque chose de similaire, j'ai pensé que je voudrais partager des solutions aux Questions connexes que j'ai rencontré. J'espère que ça aidera quelqu'un.
C'est beaucoup plus en profondeur et portera sur les éléments suivants:
- Bien sûr: le réglage de la hauteur d'un
UITableViewCell
basé sur la taille nécessaire pour afficher le contenu complet d'un contenue UITextView
- Répondre à des modifications du texte (et d'animer la hauteur de la ligne)
- En gardant le curseur à l'intérieur de la zone visible et de maintien de premiers répondants sur l'
UITextView
lors du redimensionnement de la UITableViewCell
lors de l'édition
Si vous travaillez avec un tableau statique de la vue ou vous avez seulement un nombre connu d' UITextView
s, vous pouvez potentiellement faire de l'étape 2 est beaucoup plus simple.
1. Tout d'abord, remplacer le 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. Définir la fonction qui calcule le besoin de la hauteur:
Ajouter un NSDictionary
(dans cet exemple appelle textViews
) comme une variable d'instance de votre UITableViewController
sous-classe.
L'utilisation de ce dictionnaire pour stocker les références à la personne UITextViews
comme:
(et oui, indexPaths sont les clés valides pour les dictionnaires)
- (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;
}
Cette fonction va maintenant calculer la hauteur réelle:
- (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. Activer le Redimensionnement lors de l'Édition
Pour les deux fonctions, il est important, que le délégué de l' UITextViews
est mis à votre UITableViewController
. Si vous avez besoin de quelque chose d'autre en tant que délégué, vous pouvez contourner le problème en faisant l'appel, ou bien, à l'aide de la NSNotificationCenter crochets.
- (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. Suivez curseur lors de l'Édition
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Cela va rendre l' UITableView
faites défiler jusqu'à la position du curseur, si elle n'est pas dans le visible Rect de la UITableView:
- (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. Ajuster visible rect, en définissant les encarts
Pendant le montage, les pièces de votre UITableView
peuvent être couverts par le Clavier. Si le tableviews encarts ne sont pas ajustés, scrollToCursorForTextView:
ne sera pas en mesure de faire défiler le curseur, si il est en bas de la tableview.
- (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];
}
Et la dernière partie:
À l'intérieur de votre point de vue ne charge, inscrivez-vous pour les Notifications pour Clavier changements par le biais d' 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];
}
Veuillez ne pas obtenir en colère contre moi, pour la fabrication de cette réponse si longtemps. Bien que pas tous, il est nécessaire de répondre à la question, je crois qu'il y a d'autres personnes qui directement liés à des questions leur seront utiles.
Mise à JOUR:
Comme Dave Haupert souligné, j'ai oublié d'inclure l' rectVisible
fonction de:
- (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);
}
Aussi, j'ai remarqué, que scrollToCursorForTextView:
toujours inclus une référence directe à l'un des objets textfield dans mon projet. Si vous avez un problème avec bodyTextView
de ne pas être trouvé, vérifiez la version mise à jour de la fonction.