Comment dimensionner une UITextView à son contenu?


521

Existe-t-il un bon moyen d'ajuster la taille d'un UITextViewpour l'adapter à son contenu? Disons par exemple que j'ai un UITextViewqui contient une ligne de texte:

"Hello world"

J'ajoute ensuite une autre ligne de texte:

"Goodbye world"

Existe-t-il un bon moyen dans Cocoa Touch pour obtenir le rectcontenu de toutes les lignes de la vue texte afin de pouvoir ajuster la vue parent en conséquence?

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


veuillez envisager de mettre à jour la bonne réponse, car celle acceptée conduit à des calculs inutiles, il existe maintenant une propriété contentSize pour ce problème.
Juan Boero

Réponses:


610

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 souhaitez prendre en charge iOS 6.1, vous devez également:

textview.scrollEnabled = NO;

1
Testé sur iOS 7 pour redimensionner une UITextView en une UITableViewCell. Fonctionne vraiment très bien. C'est la seule réponse qui a finalement fonctionné pour moi. Merci!
Alex

37
J'avais besoin de textview.scrollEnabled = NO;pour éviter que le texte ne soit coupé même dans iOS 7.
Brian

19
Je recommande d'utiliser la CGFLOAT_MAXmacro au lieu de MAXFLOAT. Adapté aux deux plates-formes 32/64 bits.
Eonil

3
Celui qui fait face à peu de fluctuations avant d'entrer dans la ligne suivante ajoute ce `NSRange bottom = NSMakeRange (textView.text.length -1, 1); [textView scrollRangeToVisible: bottom]; `
ajay_nasa

4
Pourquoi y a-t-il deux appels distincts à sizeThatFits (...) dans la version Swift? À quoi sert la première ligne?
nekonari

576

Cela ne fonctionne plus sur iOS 7 ou supérieur

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

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

Une chose à noter est que le bon contentSizeest uniquement disponible après l' UITextViewa été ajouté à la vue avecaddSubview . Avant cela, il est égal àframe.size

Cela ne fonctionnera pas si la disposition automatique est activée. Avec la disposition automatique, l'approche générale consiste à utiliser la sizeThatFitsméthode et à mettre à jour la constantvaleur sur une contrainte de hauteur.

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

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


Pour ajouter à cette étonnante réponse, 2014, si vous:

[self.textView sizeToFit];

il y a une différence de comportement avec l' iPhone6 ​​+ uniquement:

entrez la description de l'image ici

Avec le 6+ seulement (pas le 5s ou le 6), il ajoute "une ligne vierge de plus" à l'UITextView. La "solution RL" corrige parfaitement cela:

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+.


2
Tu m'as sauvé la journée. J'avais du mal avec l'extension de fonction de classe selfCalculating en oubliant cela. Merci.
Lukasz

4
Aha! Je définissais la hauteur de la vue texte, puis ajustais la hauteur de la vue contenant. Apparemment, quand je l'ai fait, la hauteur de la vue texte était en cours de réglage. La définition de la hauteur de la vue contenant en premier fait fonctionner les choses comme prévu (ou, mieux, espéré).
Hot Licks

11
L'utilisation de [_textView sizeToFit] actualise la propriété contentSize, supprimant la nécessité de l'ajouter au scrollView au préalable.
Rodrigo

1
Si vous utilisez la mise en page automatique, appelez layoutIfNeededsur la vue d'ensemble. Ensuite, vous pouvez saisir la hauteur contentSize.
phatmann

4
Il s'agit cependant de redimensionner le conteneur extérieur. Ce comportement a changé dans iOS 7. Je montre dans la question liée où ajouter sizeToFit et layoutIfNeeded.
Henrik Erlandsson

93

Pour faire un dimensionnement dynamique à l' UITextViewintérieur d'un UITableViewCell, j'ai trouvé que la combinaison suivante fonctionne dans Xcode 6 avec le SDK iOS 8:

  • Ajouter un UITextViewà un UITableViewCellet le contraindre sur les côtés
  • Définissez la UITextViewde » scrollEnabledpropriété à NO. Avec le défilement activé, le cadre du UITextViewest 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 d'origine de 44, il calculera automatiquement les hauteurs de ligne, mais si vous avez changé la hauteur de ligne par défaut pour autre chose, vous devrez peut-être activer manuellement le calcul automatique des hauteurs de ligne dans viewDidLoad:

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

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

  • Implémentez la textViewDidChange:méthode du UITextViewDelegateprotocole et dites à la tableViewde se repeindre à chaque fois que le texte est édité:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
  • Et n'oubliez pas de placer le UITextViewdélégué quelque part, dans Storyboardou entableView:cellForRowAtIndexPath:


Meilleure réponse pour moi. Fonctionne parfaitement et UITableViewAutomaticDimension a été ajouté dans iOS 5, il est donc rétrocompatible.
smmelzer

4
Ça n'a pas vraiment marché pour moi. La méthode textViewDidChange fait rebondir ma table à chaque fois que je tape un caractère. Ce que je suggère, c'est qu'au lieu d'utiliser cette méthode, dans la méthode tableView: cellForRowAtIndexPath, pour la ligne avec la vue textuelle, si vous êtes dans un mode en lecture seule .scrollEnabled sur NO, et si vous êtes dans un ensemble de vues d'édition faites défiler jusqu'à YES. De cette façon, lorsque vous l'afficherez, le texte intégral s'affichera toujours et lors de sa modification, il commencera par le texte intégral et, lorsque vous ajouterez du texte, il restera de la même taille avec le texte précédent défilant en haut
SimonTheDiver

3
en outre, j'ai ajouté une contrainte> = hauteur à la vue de texte car un champ de texte vide n'avait pas de hauteur et ne pouvait pas être activé pour commencer l'édition.
SimonTheDiver

Excellente solution. Pour moi, tableView.rowHeight = UITableViewAutomaticDimensionc'était inutile.
Christopher Pickslay

Merci encore Brett Donald! J'ai oublié comment faire cela et j'ai retrouvé votre réponse plus d'un an plus tard 😀.
Eric Conner

76

Solution de travail très simple utilisant à la fois du code et un storyboard.

Par code

textView.scrollEnabled = false

Par Storyboard

Décochez la case Activer le défilement

entrez la description de l'image ici

Pas besoin de faire quoi que ce soit d'autre.


5
Cette réponse est correcte. Dans StoryBoard, vous avez le TextView AutoSize comme un UILabel. Tout ce que nous devons faire est de définir scrollEnabled = false.
pnavk

4
Essentiellement, cela est correct: si vous utilisez des contraintes de mise en page automatique et désactivez le défilement, tout fonctionne.
Dan Rosenstark

2
Merci beaucoup. C'était aussi simple que cela, il suffit de désactiver le défilement dans le storyboard ou le code, ce sera comme UILabel avec les lignes 0.
samir105

@Mansuu .... Ce n'est pas une solution garantie, car il y a des choses que vous pouvez faire pour remplacer la taille intrinsèque du contenu, et si vous modifiez le texte après la présentation de la vue, il ne sera pas mis à jour à moins que vous ne le définissiez aussi. Mais, ces choses restent vraies pour la définition de numberOfLines = 0 sur un champ de texte également. Si cela ne fonctionne pas, vous avez probablement d'autres contraintes qui définiront implicitement une hauteur.
Jake T.

2
@iOS si vous ajoutez une contrainte de hauteur, réduisez la priorité des contraintes, sinon cela ne fonctionnera pas.
Alok

61

Rapide :

textView.sizeToFit()

14
De plus, j'ai constaté que je devais définir le défilement activé sur false pour que cela fonctionne. textView.scrollEnabled = false
tmarkiewicz

1
Vous devez vous rappeler d'appeler textView.layoutIfNeeded () après textView.sizeToFit ()
Daniel Kuta

5
@tmarkiewicz Cela fonctionne lorsque le texte tient sur l'écran de votre appareil, mais ce sera un problème lorsque votre texte sera plus grand que l'espace qu'il y a à l'écran. Vous ne pourrez pas le faire défiler pour voir le reste du texte.
Francisco Romero

Telle est la réponse !!! Pas besoin de solutions plus compliquées !!! @FranciscoRomero Pourquoi ne pas mettre la vue textuelle dans une cellule de tableau ou une cellule de vue de colleciton alors vous pouvez toujours faire défiler le tableau ou la vue de colleciton ....
Ben Smith

23

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, vous pouvez donc vous retrouver avec beaucoup plus court CGSizeque ce qui est réellement requis.

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

semble respecter les nouvelles lignes.

De plus, le texte n'est pas réellement affiché en haut de la UITextView. Dans mon code, j'ai défini la nouvelle hauteur de la UITextViewpour être 24 pixels plus grande que la hauteur renvoyée par les sizeOfFontméthodes.


3
Cela obtient la taille comme s'il dessinait le texte sur un UILabel. Si vous définissez cette taille sur le cadre de uitextview, vous aurez toujours un certain défilement nécessaire.
Kevlar

22

Dans iOS6, vous pouvez vérifier la contentSizepropriété d'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;
    }
}

2
Où puis-je en savoir plus à ce sujet? Je suis totalement perdu quant au comportement apparemment nouveau dans iOS 7 à ce sujet.
Stian Høiland

Quelle est la signification de la taille variable de CGSize?
Tchelow

J'ai supprimé la taille, elle n'était pas censée être là.
phatmann

18

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

Voici le dépôt gitHub pour ceux qui ne veulent pas lire tout ce texte: resizableTextView

Cela fonctionne avec iOs7 (et je pense que cela fonctionnera avec iOs8) et avec la mise en page automatique. Vous n'avez pas besoin de nombres magiques, désactivez la mise en page et des trucs comme ça. Solution courte et élégante.

Je pense que tout le code lié aux contraintes devrait aller à la updateConstraintsméthode. Alors, faisons le nôtre ResizableTextView.

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

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

Alors maintenant, nous connaissons le vrai contenu, quelle que soit notre position: avant ou après viewDidLoad . Ajoutez maintenant une 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 à la superclasse updateConstraints .

[super updateConstraints];

Maintenant, notre classe 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];
}

Joli et propre, non? Et vous n'avez pas à traiter avec ce code dans votre contrôleurs !

Mais attendez! OU PAS D'ANIMATION!

Vous pouvez facilement animer les modifications pour effectuer un textViewétirement en douceur. 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];

4
Utilisez CGFLOAT_MAXpas FLT_MAX.
rob mayoff

J'aimerais pouvoir vous donner plus d'un vote pour cette solution géniale !!
Scooter

13

As-tu essayé [textView sizeThatFits:textView.bounds] ?

Edit: sizeThatFits renvoie la taille mais ne redimensionne pas réellement le composant. Je ne sais pas si c'est ce que vous voulez, ou si [textView sizeToFit]c'est plus ce que vous cherchiez. Dans les deux cas, je ne sais pas si cela s'adaptera parfaitement au contenu comme vous le souhaitez, mais c'est la première chose à essayer.


2
sizetofit sauve la mise
michaelsnowden

9

Une autre méthode consiste à trouver la taille qu'une chaîne particulière prendra en utilisant la NSStringméthode:

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

Cela renvoie la taille du rectangle qui correspond à la chaîne donnée avec la police donnée. Passez une taille avec la largeur souhaitée et une hauteur maximale, puis vous pouvez regarder la hauteur retournée pour s'adapter au texte. Il existe une version qui vous permet également de spécifier le mode de saut de ligne.

Vous pouvez ensuite utiliser la taille renvoyée pour modifier la taille de votre vue pour l'adapter.


8

Si vous ne disposez pas de l' UITextViewoutil pratique (par exemple, vous dimensionnez des cellules de vue de tableau), vous devrez calculer la taille en mesurant la chaîne, puis en tenant compte des 8 pt de rembourrage de chaque côté de a UITextView. Par exemple, si vous connaissez la largeur souhaitée de votre affichage de texte et que vous souhaitez déterminer la hauteur correspondante:

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;

CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

Ici, chaque 8 représente l'un des quatre bords rembourrés, et 100000 sert simplement de très grande taille maximale.

En pratique, vous voudrez peut-être ajouter un supplément font.leadingà la hauteur; cela ajoute une ligne vierge en dessous de votre texte, ce qui peut sembler mieux s'il y a des contrôles visuellement lourds directement sous la vue du texte.


résultat parfait dans iOS 8.1
Logic

Le rembourrage était la clé pour moi
thibaut noah

8

On peut le faire par contraintes.

  1. Définissez les contraintes de hauteur pour UITextView. entrez la description de l'image ici

2.Créez IBOutlet pour cette contrainte de hauteur.

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3. n'oubliez pas de définir délégué pour votre affichage de texte.

4.

-(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);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

puis mettez à jour votre contrainte comme ceci :)


c'est un surnom FANTASTIQUE!
Fattie

La définition de la constante doit être suivie de [textView layoutIfNeeded]; dans le bloc d'animation. (Les animations de mise en page automatique le font comme ça.)
Will Larche

7

Les choses suivantes suffisent:

  1. N'oubliez pas de définir le défilement activé sur NON pour votre UITextView:

entrez la description de l'image ici

  1. Définissez correctement les contraintes de mise en page automatique.

Vous pouvez même utiliser UITableViewAutomaticDimension.


6

Combiné avec la réponse de Mike McMaster, vous voudrez peut-être faire quelque chose comme:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}

6

J'ai trouvé un moyen de redimensionner la hauteur d'un champ de texte en fonction du texte qu'il contient et d'organiser également une étiquette en dessous en fonction de la hauteur du champ de texte! Voici le code.

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;

[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];

Ici, le '5' en coordonnée y de UILabel est l'écart que je veux entre textView et Label.
dheeraj

6

Les gars utilisant la mise en page automatique et votre taille ne fonctionnent pas, alors vérifiez une fois votre contrainte de largeur. Si vous avez manqué la contrainte de largeur, la hauteur sera précise.

Pas besoin d'utiliser une autre API. une seule ligne réglerait tout le problème.

[_textView sizeToFit];

Ici, je ne me préoccupais que de la hauteur, en gardant la largeur fixe et j'avais manqué la contrainte de largeur de mon TextView dans le storyboard.

Et c'était pour montrer le contenu dynamique des services.

J'espère que cela pourrait aider ..


6

À partir d'iOS 8, il est possible d'utiliser les fonctionnalités de mise en page automatique d'un UITableView pour redimensionner automatiquement un UITextView sans aucun code personnalisé. J'ai mis un projet dans github qui le démontre en action, mais voici la clé:

  1. Le défilement UITextView doit être désactivé, ce que vous pouvez faire par programme ou via le générateur d'interface. Il ne sera pas redimensionné si le défilement est activé car le défilement vous permet de visualiser le contenu plus volumineux.
  2. Dans viewDidLoad pour UITableViewController, vous devez définir une valeur pour estimationRowHeight, puis définissez le rowHeightsur UITableViewAutomaticDimension.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. La cible de déploiement du projet doit être iOS 8 ou une version ultérieure.

1
Ce genre de réponses est déconseillé. Vous devez publier le code correspondant ici.
Antzi

5

J'ai passé en revue toutes les réponses et toutes gardent une largeur fixe et ajustent uniquement la hauteur. Si vous souhaitez régler également la largeur, vous pouvez très facilement utiliser cette méthode:

donc lors de la configuration de votre affichage texte, désactivez le défilement

textView.isScrollEnabled = false

puis dans la méthode déléguée, func textViewDidChange(_ textView: UITextView)ajoutez ce code:

func textViewDidChange(_ textView: UITextView) {
    let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}

Les sorties:

entrez la description de l'image ici

entrez la description de l'image ici


La méthode déléguée ne s'appelle pas @Peter Stajger
Mansuu ....

4

Cela a bien fonctionné lorsque j'ai eu besoin de faire du texte dans une UITextViewzone spécifique:

// Le texte doit déjà être ajouté à la sous-vue, sinon contentviewsize sera incorrect.

- (void) ReduceFontToFit: (UITextView *) tv {
    UIFont * font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height> tv.frame.size.height && pointSize> 7.0) {
        pointSize - = 1.0;
        UIFont * newFont = [UIFont fontWithName: font.fontName size: pointSize];
        tv.font = newFont;
    }
    if (pointSize! = font.pointSize)
        NSLog (@ "police jusqu'à% .1f de% .1f", pointSize, tv.font.pointSize);
}

4

voici la version rapide de @jhibberd

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
    cell.msgText.text = self.items[indexPath.row]
    var fixedWidth:CGFloat = cell.msgText.frame.size.width
    var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
    var newSize:CGSize = cell.msgText.sizeThatFits(size)
    var newFrame:CGRect = cell.msgText.frame;
    newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
    cell.msgText.frame = newFrame
    cell.msgText.frame.size = newSize        
    return cell

6
La question est vraiment indépendante de la langue. Est-il vraiment nécessaire de revenir en arrière et d'écrire des ports rapides pour toutes les réponses aux questions liées à UIKit? On dirait que ça fait une conversation bruyante.
eremzeit

le problème que la plupart de ces questions n'a pas de langage de programmation spécifique, vous le trouverez donc dans google même si vous recherchez un langage rapide
Fareed Alnamrouti

4

désactiver le défilement

ajouter des contraintes

et ajoutez votre texte

[yourTextView setText:@"your text"];
[yourTextView layoutIfNeeded];

si vous utilisez, UIScrollViewvous devez également l'ajouter;

[yourScrollView layoutIfNeeded];

-(void)viewDidAppear:(BOOL)animated{
    CGRect contentRect = CGRectZero;

    for (UIView *view in self.yourScrollView.subviews) {
         contentRect = CGRectUnion(contentRect, view.frame);
    }
    self.yourScrollView.contentSize = contentRect.size;
}

3

Pour iOS 7.0, au lieu de définir frame.size.heightl'utilisation contentSize.height(qui ne fait actuellement rien) [textView sizeToFit].

Voir cette question .


2

L'utilisation de UITextViewDelegate est le moyen le plus simple:

func textViewDidChange(_ textView: UITextView) {
    textView.sizeToFit()
    textviewHeight.constant = textView.contentSize.height
}

1

J'espère que cela t'aides:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}

Ça ne marche pas! Il provoque une erreur: "lvalue requise comme opérande gauche d'affectation"
leviathan

Vous ne pouvez affecter qu'à textView.frame.
jweyrich

1

si d'autres arrivent ici, cette solution fonctionne pour moi, 1 "Ronnie Liew" +4 "user63934" (mon texte arrive du service web): notez le 1000 (rien ne peut être si gros "dans mon cas")

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];

NSString *dealDescription = [client objectForKey:@"description"];

//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];

CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);

UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];

dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];

//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

Et c'est ... Vive


1

Le meilleur moyen que j'ai découvert pour redimensionner la hauteur de l'UITextView en fonction de la taille du texte.

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

ou vous pouvez UTILISER

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];

1

Pour ceux qui veulent que la vue texte se déplace vers le haut et maintienne la position de la ligne de fond

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

if(frame.size.height > textView.frame.size.height){
    CGFloat diff = frame.size.height - textView.frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
    CGFloat diff = textView.frame.size.height - frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}

1

Le seul code qui fonctionnera est celui qui utilise 'SizeToFit' comme dans la réponse jhibberd ci-dessus, mais en réalité il ne reprendra que si vous l'appelez dans ViewDidAppear ou le câblez à l'événement de modification de texte UITextView.


1

Sur la base de la réponse de Nikita Took, je suis arrivé à la solution suivante dans Swift qui fonctionne sur iOS 8 avec la mise en page automatique:

    descriptionTxt.scrollEnabled = false
    descriptionTxt.text = yourText

    var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
    for c in descriptionTxt.constraints() {
        if c.isKindOfClass(NSLayoutConstraint) {
            var constraint = c as! NSLayoutConstraint
            if constraint.firstAttribute == NSLayoutAttribute.Height {
                constraint.constant = contentSize.height
                break
            }
        }
    }

1

Réponse rapide: le code suivant calcule la hauteur de votre textView.

                let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX)
                let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin
                let attribute = [NSFontAttributeName: textView.font!]
                let str = NSString(string: message)
                let labelBounds = str.boundingRectWithSize(maximumLabelSize,
                    options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                    attributes: attribute,
                    context: nil)
                let myTextHeight = CGFloat(ceilf(Float(labelBounds.height)))

Vous pouvez maintenant définir la hauteur de votre texte myTextHeight


Désolé, qu'est-ce que cela signifie: let attribute = [NSFontAttributeName: textView.text.font!] est-ce vraiment du code Swift sans erreurs?) Vouliez-vous dire let attribute = [NSFontAttributeName: textView.font!]
Massmaker
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.