Atualizado para 2019
É um dos erros mais bobos do iOS.
A classe dada aqui UITextViewFixed
é geralmente a solução mais razoável em geral.
Aqui está a classe:
@IBDesignable class UITextViewFixed: UITextView {
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
func setup() {
textContainerInset = UIEdgeInsets.zero
textContainer.lineFragmentPadding = 0
}
}
Não se esqueça de desativar o scrollEnabled no Inspetor!
A solução funciona corretamente no storyboard
A solução funciona corretamente em tempo de execução
É isso aí, você terminou.
Em geral, isso deve ser tudo o que você precisa na maioria dos casos .
Mesmo se você estiver alterando a altura da exibição de texto em tempo real , UITextViewFixed
geralmente faz tudo o que precisa.
(Um exemplo comum de alterar a altura em tempo real é alterá-la conforme o usuário digita.)
Aqui está o UITextView quebrado da Apple ...
Aqui está UITextViewFixed
:
Note que é claro que você deve
desative o scrollEnabled no Inspetor!
Não se esqueça de desativar o scrollEnabled! :)
Algumas questões adicionais
(1) Em alguns casos incomuns - por exemplo, em mesas com alturas de células flexíveis e dinamicamente variáveis - a Apple faz uma coisa bizarra: adicionam espaço extra na parte inferior . Não mesmo! Isso teria que ser uma das coisas mais irritantes no iOS.
Aqui está uma "solução rápida" a ser adicionada acima, que geralmente ajuda com essa loucura.
...
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) Às vezes, para corrigir outra bagunça sutil da Apple, você deve adicionar o seguinte:
override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
super.setContentOffset(contentOffset, animated: false)
}
(3) Indiscutivelmente, devemos acrescentar:
contentInset = UIEdgeInsets.zero
logo depois de .lineFragmentPadding = 0
entrar UITextViewFixed
.
No entanto ... acredite ou não ... simplesmente não funciona no iOS atual! (Verificado em 2019.) Pode ser necessário adicionar essa linha no futuro.
O fato de UITextView
ser quebrado no iOS é uma das coisas mais estranhas em toda a computação móvel. Aniversário de dez anos desta pergunta e ainda não foi corrigido!
Finalmente, aqui está uma dica um pouco semelhante para o campo de texto : https://stackoverflow.com/a/43099816/294884
Dica completamente aleatória: como adicionar o "..." no final
Muitas vezes você está usando um UITextView "como um UILabel". Então, você deseja que ele trunque o texto usando as reticências "..."
Nesse caso, adicione uma terceira linha de código na "instalação":
textContainer.lineBreakMode = .byTruncatingTail
Dica prática, se você quiser altura zero, quando não houver texto
Geralmente, você usa uma exibição de texto para exibir apenas o texto. Portanto, o usuário não pode editar nada. Você usa as linhas "0" para significar que a exibição do texto mudará automaticamente de altura, dependendo de quantas linhas de texto.
Isso é ótimo, mas se não houver texto , infelizmente, você terá a mesma altura como se houvesse uma linha de texto ! A exibição de texto nunca "desaparece".
Se você quiser "desaparecer", basta adicionar este
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
}
(Eu fiz '1' para ficar claro o que está acontecendo, '0' está bom.)
E o UILabel?
Ao exibir apenas o texto, o UILabel tem muitas vantagens sobre o UITextView. O UILabel não sofre dos problemas descritos nesta página de controle de qualidade. De fato, a razão pela qual todos "desistimos" e apenas usamos o UITextView é que é difícil trabalhar com o UILabel. Em particular, é ridiculamente difícil adicionar apenas preenchimento , corretamente, ao UILabel. De fato, aqui está uma discussão completa sobre como "finalmente" adicionar preenchimento corretamente ao UILabel: https://stackoverflow.com/a/58876988/294884 Em alguns casos, se você estiver fazendo um layout difícil com células dinâmicas de altura, às vezes é melhor fazê-lo da maneira mais difícil com o UILabel.