À jour pour 2019
C'est l'un des bogues les plus stupides d'iOS.
La classe donnée ici UITextViewFixed
est généralement la solution la plus raisonnable.
Voici la classe:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
N'oubliez pas de désactiver scrollEnabled dans l'inspecteur!
La solution fonctionne correctement dans le storyboard
La solution fonctionne correctement lors de l'exécution
Voilà, vous avez terminé.
En général, cela devrait être tout ce dont vous avez besoin dans la plupart des cas .
Même si vous modifiez la hauteur de la vue texte à la volée , fait UITextViewFixed
généralement tout ce dont vous avez besoin.
(Un exemple courant de modification de la hauteur à la volée est de la modifier au fur et à mesure que l'utilisateur tape.)
Voici le UITextView cassé d'Apple ...
Voici UITextViewFixed
:
Notez bien sûr que vous devez
désactiver scrollEnabled dans l'inspecteur!
N'oubliez pas de désactiver scrollEnabled! :)
Quelques autres problèmes
(1) Dans certains cas inhabituels - par exemple, certains cas de tables avec des hauteurs de cellule flexibles et changeantes dynamiquement - Apple fait une chose bizarre: ils ajoutent de l'espace supplémentaire en bas . Pas vraiment! Cela devrait être l'une des choses les plus exaspérantes d'iOS.
Voici une "solution miracle" à ajouter à ce qui précède qui aide généralement à cette folie.
...
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
// this is not ideal, but you can sometimes use this
// to fix the "extra space at the bottom" insanity
var b = bounds
let h = sizeThatFits(CGSize(
width: bounds.size.width,
height: CGFloat.greatestFiniteMagnitude)
).height
b.size.height = h
bounds = b
...
(2) Parfois, pour corriger un autre subtil désordre d'Apple, vous devez ajouter ceci:
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false)
}
(3) Sans doute, nous devrions ajouter:
contentInset = UIEdgeInsets.zero
juste après .lineFragmentPadding = 0
dans UITextViewFixed
.
Cependant ... croyez ou non ... cela ne fonctionne tout simplement pas dans iOS actuel! (Vérifié en 2019.) Il peut être nécessaire d'ajouter cette ligne à l'avenir.
Le fait que cela UITextView
soit cassé dans iOS est l'une des choses les plus étranges de tout l'informatique mobile. Dixième anniversaire de cette question et ce n'est toujours pas résolu!
Enfin, voici une astuce quelque peu similaire pour Text Field : https://stackoverflow.com/a/43099816/294884
Astuce complètement aléatoire: comment ajouter le "..." à la fin
Souvent, vous utilisez un UITextView "comme un UILabel". Vous voulez donc qu'il tronque le texte en utilisant des points de suspension "..."
Si oui, ajoutez une troisième ligne de code dans le "setup":
textContainer.lineBreakMode = .byTruncatingTail
Astuce pratique si vous voulez une hauteur nulle, quand, il n'y a pas de texte du tout
Souvent, vous utilisez une vue texte pour n'afficher que du texte. Ainsi, l'utilisateur ne peut rien modifier. Vous utilisez les lignes "0" pour signifier que la vue du texte changera automatiquement de hauteur en fonction du nombre de lignes de texte.
C'est super, mais s'il n'y a pas de texte du tout, malheureusement, vous obtenez la même hauteur que s'il y a une ligne de texte !! La vue texte ne "disparaît" jamais.
Si vous voulez qu'il "s'en aille", ajoutez simplement ceci
override var intrinsicContentSize: CGSize {
var i = super.intrinsicContentSize
print("for \(text) size will be \(i)")
if text == "" { i.height = 1.0 }
print(" but we changed it to \(i)")
return i
}
(Je l'ai fait «1» donc il est clair ce qui se passe, «0» est très bien.)
Et UILabel?
Lors de l'affichage de texte, UILabel présente de nombreux avantages par rapport à UITextView. UILabel ne souffre pas des problèmes décrits sur cette page QA. En effet, la raison pour laquelle nous «abandonnons» habituellement et utilisons simplement UITextView est qu'il est difficile de travailler avec UILabel. En particulier, il est ridiculement difficile de simplement ajouter un rembourrage , correctement, à UILabel. En fait, voici une discussion complète sur la façon d'ajouter "enfin" correctement le remplissage à UILabel: https://stackoverflow.com/a/58876988/294884 Dans certains cas, si vous effectuez une mise en page difficile avec des cellules de hauteur dynamique, il est parfois il vaut mieux le faire à la dure avec UILabel.