Question Comment dimensionner un UITextView à son contenu?


Y a-t-il un bon moyen d'ajuster la taille d'un UITextView se conformer à son contenu? Dites par exemple que j'ai un UITextView qui contient une ligne de texte:

"Hello world"

J'ajoute ensuite une autre ligne de texte:

"Goodbye world"

Y at-il un bon moyen de Cocoa Touch pour obtenir le rect cela tiendra toutes les lignes dans la vue de texte afin que je puisse ajuster la vue parent en conséquence?

Comme un autre exemple, regardez le champ des notes pour les événements dans l'application Calendrier - notez comment la cellule (et la UITextView il contient) se développe pour contenir toutes les lignes de texte dans la chaîne des notes.


464
2017-09-08 19:21


origine


Réponses:


Cela fonctionne pour iOS 6.1 et iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    textView.frame = newFrame;
}

Ou dans Swift (Fonctionne avec Swift 4.1 dans iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

Si vous voulez un support pour iOS 6.1, vous devriez également:

textview.scrollEnabled = NO;

532
2017-09-21 10:26



Cela ne fonctionne plus sur iOS 7 ou supérieur

Il y a en fait un moyen très simple de redimensionner le UITextView à sa hauteur correcte du contenu. Cela peut être fait en utilisant UITextView  contentSize.

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

Une chose à noter est que le bon contentSize est seulement disponible après la UITextView a été ajouté à la vue avec addSubview. Avant cela, il est égal à frame.size

Cela ne fonctionnera pas si la mise en page automatique est activée. Avec la mise en page automatique, l’approche générale consiste à utiliser le sizeThatFits méthode et mettre à jour le constant valeur sur une contrainte de hauteur.

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraint est une contrainte de mise en page que vous configurez généralement via un IBOutlet en liant la propriété à la contrainte de hauteur créée dans un storyboard.


Juste pour ajouter à cette réponse incroyable, 2014, si vous:

[self.textView sizeToFit];

il y a une différence de comportement avec le iPhone6 ​​+ seulement:

enter image description here

Avec le 6+ seulement (pas le 5 ou le 6), il ajoute "une ligne vide" à UITextView. La "solution RL" corrige parfaitement ceci:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

Il corrige le problème de "ligne supplémentaire" sur 6+.


570
2018-03-21 14:26



Pour faire un dimensionnement dynamique UITextView à l'intérieur UITableViewCell, J'ai trouvé la combinaison suivante fonctionne dans Xcode 6 avec le SDK iOS 8:

  • Ajouter un UITextView à un UITableViewCell et contraindre sur les côtés
  • Met le UITextViewde scrollEnabled propriété à NO. Avec le défilement activé, le cadre de la UITextView est indépendant de la taille de son contenu, mais avec le défilement désactivé, il existe une relation entre les deux.
  • Si votre table utilise la hauteur de ligne par défaut de 44, elle calcule automatiquement les hauteurs de ligne, mais si vous modifiez la hauteur de ligne par défaut, vous devrez peut-être activer manuellement le calcul automatique des hauteurs de ligne. viewDidLoad:

    tableView.estimatedRowHeight = 150;
    tableView.rowHeight = UITableViewAutomaticDimension;
    

Pour le dimensionnement dynamique en lecture seule UITextViews, c'est tout. Si vous autorisez les utilisateurs à modifier le texte dans votre UITextView, vous devez également:

  • Mettre en œuvre le textViewDidChange: méthode de UITextViewDelegate protocole, et dites le tableView pour se repeindre chaque fois que le texte est édité:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
    
  • Et n'oubliez pas de mettre le UITextView déléguer quelque part, soit dans Storyboard ou en tableView:cellForRowAtIndexPath:


82
2017-10-28 01:12



Rapide :

textView.sizeToFit()

51
2017-10-01 18:32



Juste définir

Par code

textView.scrollEnabled = false

Par Storyboard

enter image description here

Pas besoin de faire autre chose que ça.


28
2017-07-17 07:06



Dans mon expérience (limitée),

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

ne respecte pas les caractères de nouvelle ligne, de sorte que vous pouvez vous retrouver avec beaucoup plus court CGSize que ce qui est réellement requis.

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

semble respecter les nouvelles lignes.

En outre, le texte n'est pas réellement rendu en haut de la UITextView. Dans mon code, je définis la nouvelle hauteur du UITextView être 24 pixels plus grand que la hauteur retournée par le sizeOfFont méthodes


24
2018-02-08 19:01



Dans iOS6, vous pouvez vérifier contentSize propriété de UITextView juste après avoir défini le texte. Dans iOS7, cela ne fonctionnera plus. Si vous souhaitez restaurer ce comportement pour iOS7, placez le code suivant dans une sous-classe de UITextView.

- (void)setText:(NSString *)text
{
    [super setText:text];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
        UIEdgeInsets inset = self.textContainerInset;
        self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
    }
}

22
2017-09-16 21:35



Je posterai la bonne solution au bas de la page au cas où quelqu'un serait courageux (ou assez désespéré) pour lire ce point.

Voici le repo gitHub pour ceux qui ne veulent pas lire tout ce texte: resizableTextView

Cela fonctionne avec iOs7 (et je crois que cela fonctionnera avec iOs8) et avec autolayout. Vous n'avez pas besoin de chiffres magiques, désactivez la mise en page et ce genre de choses. Solution courte et élégante.

Je pense que tout code lié aux contraintes devrait aller à updateConstraints méthode. Alors faisons notre propre ResizableTextView.

Le premier problème que nous rencontrons ici est que vous ne connaissez pas la taille réelle du contenu avant viewDidLoad méthode. Nous pouvons prendre la route longue et difficile et la calculer en fonction de la taille de la police, des sauts de ligne, etc. Mais nous avons besoin d'une solution robuste, donc nous allons faire:

CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

Nous connaissons maintenant le vrai contenu, peu importe où nous sommes: avant ou après viewDidLoad. Ajoutez maintenant la contrainte de hauteur sur textView (via le storyboard ou le code, peu importe comment). Nous ajusterons cette valeur avec notre contentSize.height:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

La dernière chose à faire est de dire superclasse à updateConstraints.

[super updateConstraints];

Maintenant, notre cours ressemble à:

ResizableTextView.m

- (void) updateConstraints {
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

Jolie et propre, non? Et vous n'avez pas à faire face à ce code dans votre contrôleurs!

Mais attendez! Y PAS D'ANIMATION!

Vous pouvez facilement animer les changements pour faire textView étirer doucement. Voici un exemple:

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];

17
2017-07-25 07:32