Comment ajuster la hauteur d'un textview à son contenu dans SWIFT?

dans mon contrôleur de vue, j'ai un UITextView. Ce textview est rempli d'une chaîne de caractères. La corde peut être courte ou longue. En fonction de la longueur de la chaîne, la hauteur de la textview pour ajuster. J'utilise des storyboards et de la mise en page automatique.

j'ai quelques problèmes avec la hauteur de la textview.

parfois, la hauteur est parfaitement ajustée au texte. Parfois, non, le texte est rognée sur la première ligne. Ci-dessous, le textview est jaune. le bleu est une containerview à l'intérieur d'un scrollview. Le violet est la place pour une photo.

title1title2

les textes proviennent de ma base de données de base, ce sont des attributs de chaîne. Entre l'écran 1 et 2, la seule chose changée est la chaîne.

Si j'ai l'impression que les cordes dans la console j'ai les textes :

my amazing new title

Another funny title for demo

Les contraintes de mon textview :

enter image description here

je ne comprends pas pourquoi je avoir 2 écrans différents.

EDIT

j'ai essayé le Conseil @Nate, dans viewDidLoad, j'ai ajouté:

    myTextViewTitle.text="my amazing new title"

    myTextViewTitle.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setContentCompressionResistancePriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setTranslatesAutoresizingMaskIntoConstraints(false)  

    let views = ["new_view": myTextViewTitle]
    var constrs = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[new_view]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: views)
    self.view.addConstraints(constrs)
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[new_view]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))
    self.myTextViewTitle.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[new_view(220@300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))

Pas de résultats. Avec ou sans contraint hauteur ajouté pour mon TextView in interface builder...

EDIT 2

j'ai besoin d'un UITextView et non D'un UIlabel, à cause du bouton back, pour utiliser un chemin d'exclusion.

     let exclusionPathBack:UIBezierPath = UIBezierPath(rect: CGRect(x:backButton.bounds.origin.x, y:backButton.bounds.origin.y, width:backButton.bounds.width+10, height:backButton.bounds.height))
     myTextViewTitle.textContainer.exclusionPaths=[exclusionPathBack]
23
demandé sur cmii 2015-04-03 15:11:09

7 réponses

j'ai trouvé une solution.

je me concentrais sur la hauteur de mon UITextView, puis j'ai lu un billet parlant du format d'image. Je voulais essayer et ça a marché!

donc dans le storyboard, j'ai ajouté un rapport d'aspect pour le textview, et j'ai coché "Supprimer au moment de la construction" option.

Dans viewDidLayoutSubviews(), j'ai écrit :

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    let contentSize = self.myTextViewTitle.sizeThatFits(self.myTextViewTitle.bounds.size)
    var frame = self.myTextViewTitle.frame
    frame.size.height = contentSize.height
    self.myTextViewTitle.frame = frame

    aspectRatioTextViewConstraint = NSLayoutConstraint(item: self.myTextViewTitle, attribute: .Height, relatedBy: .Equal, toItem: self.myTextViewTitle, attribute: .Width, multiplier: myTextViewTitle.bounds.height/myTextViewTitle.bounds.width, constant: 1)
    self.myTextViewTitle.addConstraint(aspectRatioTextViewConstraint!)

}

Cela fonctionne parfaitement.

40
répondu cmii 2015-04-14 18:07:17

premièrement, désactivez la scrollable UITextView. Deux options:

  1. désactiver le défilement activé .xib.
  2. [TextView setScrollEnabled: NO];

créer un UITextView et le connecter avec IBOutlet (TextView). Ajoutez une contrainte de hauteur UITextView avec hauteur par défaut, connectez-la avec IBOutlet (TextViewHeightConstraint). Lorsque vous définissez le texte D'UITextView de façon asynchrone, vous devez calculer la hauteur D'UITextView et définir la hauteur D'UITextView. la contrainte. Exemple de code:

CGSize sizeThatFitsTextView = [TextView sizeThatFits:CGSizeMake(TextView.frame.size.width, MAXFLOAT)];

TextViewHeightConstraint.constant = sizeThatFitsTextView.height; 
21
répondu Сергей Билык 2016-05-05 10:13:52

dans Swift 3.0, où tvHeightConstraint est la contrainte de hauteur du TextView sujet (si vous utilisez pour plusieurs textviews, l'ajouterait à la fonction inputs):

func textViewDidChange(textView: UITextView) {

        let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if size.height != tvHeightConstraint.constant && size.height > textView.frame.size.height{
            tvHeightConstraint.constant = size.height
            textView.setContentOffset(CGPoint.zero, animated: false)
        }
    }

H / T à @cmi et @Pablo Ruan

8
répondu agrippa 2017-06-05 18:52:00

dans swift 2.3:

 func textViewDidChange(textView: UITextView) {

    let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.max))
    if size.height != TXV_Height.constant && size.height > textView.frame.size.height{
        TXV_Height.constant = size.height
        textView.setContentOffset(CGPointZero, animated: false)
    }
}
5
répondu Pablo Ruan 2017-01-26 18:17:09

pourquoi ne pas avoir une image pour le bouton arrière et un UILabel pour votre texte, et utiliser autolayout pour les positionner? Et peut-être une troisième vue pour le fond jaune.

0
répondu Koen 2015-04-06 15:27:56

Ma solution simple à un problème similaire:

j'ai utilisé des étiquettes avec le nombre de lignes défini à 0 au lieu d'essayer d'utiliser des champs de texte ou des vues. Puis j'ai clippé les bords d'attaque et de fuite sur les conteneurs des étiquettes qui limitent leurs largeurs dans mon cas, avec 0 comme constante pour les contraintes. La capture est de définir le nombre de lignes à 0 pour permettre aux étiquettes de croître ou rétrécir en fonction de leur contenu. Le texte ne se coupe jamais et la hauteur des étiquettes ne jamais dépasser leur contenu " pour toutes les différentes classes de taille que j'ai configurées pour les largeurs (les largeurs du conteneur dans mon cas). Testé pour IOS 8.0 et plus tard (assurez - vous également que 'explicit' n'est pas coché à côté des attributs 'Preferred Width' pour tous les lables pour les largeurs d'étiquettes à ajuster pour différentes classes de taille) - fonctionne parfaitement.

0
répondu AshleyC 2016-03-10 07:04:53

j'ai adapté votre code et je l'ai utilisé pour: layout subview et textViewDidChange. Merci beaucoup ce que fait ma journée après une heure de dépannage...

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    textViewDidChange(self.recordingTitleTV)


}

func textViewDidChange(_ textView: UITextView) {

    let contentSize = textView.sizeThatFits(textView.bounds.size)
    var frame = textView.frame
    frame.size.height = contentSize.height
    textView.frame = frame

    let aspectRatioTextViewConstraint = NSLayoutConstraint(item: textView, attribute: .height, relatedBy: .equal, toItem: textView, attribute: .width, multiplier: textView.bounds.height/textView.bounds.width, constant: 1)
    textView.addConstraint(aspectRatioTextViewConstraint)
}
0
répondu AppNerd 2018-03-17 16:40:07