Aggiornato per il 2019
È uno dei bug più sciocchi in iOS.
La classe qui indicata UITextViewFixed
è generalmente la soluzione più ragionevole.
Ecco la classe:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
Non dimenticare di disattivare scrollEnabled in Inspector!
La soluzione funziona correttamente nello storyboard
La soluzione funziona correttamente in fase di esecuzione
Ecco fatto, il gioco è fatto.
In generale, dovrebbe essere tutto ciò che serve nella maggior parte dei casi .
Anche se stai modificando l'altezza della vista testo al volo , di UITextViewFixed
solito fa tutto ciò che ti serve.
(Un esempio comune di modifica dell'altezza al volo, è la modifica man mano che l'utente digita.)
Ecco il UITextView rotto da Apple ...
Ecco qui UITextViewFixed
:
Si noti che ovviamente è necessario
disattiva scrollEnabled in Inspector!
Non dimenticare di disattivare scrollEnabled! :)
Qualche ulteriore problema
(1) In alcuni casi insoliti - ad esempio, alcuni casi di tavoli con altezze di cella flessibili e che cambiano dinamicamente - Apple fa una cosa bizzarra: aggiungono spazio extra nella parte inferiore . No davvero! Questa dovrebbe essere una delle cose più esasperanti di iOS.
Ecco una "soluzione rapida" da aggiungere a quanto sopra che di solito aiuta con quella follia.
...
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) A volte, per risolvere l'ennesimo pasticcio di Apple, devi aggiungere questo:
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false)
}
(3) Probabilmente dovremmo aggiungere:
contentInset = UIEdgeInsets.zero
subito dopo .lineFragmentPadding = 0
in UITextViewFixed
.
Tuttavia ... credici o no ... semplicemente non funziona nell'attuale iOS! (Controllato nel 2019.) Potrebbe essere necessario aggiungere quella linea in futuro.
Il fatto che UITextView
si rompa in iOS è una delle cose più strane in tutto il mobile computing. Dieci anni di questa domanda e non è stato ancora risolto!
Infine, ecco un suggerimento in qualche modo simile per Campo di testo : https://stackoverflow.com/a/43099816/294884
Suggerimento completamente casuale: come aggiungere il "..." alla fine
Spesso stai usando un UITextView "come un UILabel". Quindi vuoi che tronci il testo usando i puntini di sospensione "..."
In tal caso, aggiungi una terza riga di codice nel "setup":
textContainer.lineBreakMode = .byTruncatingTail
Consiglio pratico se si desidera un'altezza pari a zero, quando non è presente alcun testo
Spesso si utilizza una vista di testo per visualizzare solo il testo. Quindi, l'utente non può effettivamente modificare nulla. Usa le righe "0" per indicare che la vista del testo cambierà automaticamente altezza in base al numero di righe di testo.
È fantastico, ma se non c'è alcun testo, sfortunatamente si ottiene la stessa altezza di una riga di testo !! La vista di testo non "va mai via".
Se vuoi che "vada via", aggiungi questo
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
}
(L'ho fatto '1', quindi è chiaro cosa sta succedendo, '0' va bene.)
Che dire di UILabel?
Quando si visualizza solo testo, UILabel ha molti vantaggi rispetto a UITextView. UILabel non soffre dei problemi descritti in questa pagina di QA. In effetti, il motivo per cui di solito ci "arrendiamo" e usiamo UITextView è che UILabel è difficile da lavorare. In particolare è ridicolmente difficile aggiungere solo l' imbottitura , correttamente, a UILabel. In effetti, ecco una discussione completa su come "finalmente" aggiungere correttamente il riempimento a UILabel: https://stackoverflow.com/a/58876988/294884 In alcuni casi, se si sta eseguendo un layout difficile con celle ad altezza dinamica, a volte è meglio farlo nel modo più duro con UILabel.