Eu tenho um UITextView
no meu aplicativo iOS, que exibe uma grande quantidade de texto.
Então, estou paginando este texto usando o parâmetro offset margin do UITextView
.
Meu problema é que o preenchimento do UITextView
é confuso nos meus cálculos, pois parece ser diferente, dependendo do tamanho da fonte e do tipo de letra que eu uso.
Portanto, faço a pergunta: É possível remover o preenchimento ao redor do conteúdo do UITextView
?
Ansiosos para ouvir suas respostas!
ios
iphone
cocoa-touch
uikit
uitextview
sniurkst
fonte
fonte
Respostas:
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:
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.
(2) Às vezes, para corrigir outra bagunça sutil da Apple, você deve adicionar o seguinte:
(3) Indiscutivelmente, devemos acrescentar:
logo depois de
.lineFragmentPadding = 0
entrarUITextViewFixed
.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":
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
(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.
fonte
self.textView.isScrollEnabled = false
dentroviewDidLayoutSubviews()
e que funcionou também. A Apple só gosta de fazer-nos saltar através de aros :)translatesAutoresizingMaskIntoConstraints
. Com essa resposta, não consegui remover todas as margens (uma margem inferior estranha resistiu a desaparecer) em uma hierarquia de exibição usando o layout automático. Ele também lida com o cálculo de tamanhos de vista usandosystemLayoutSizeFitting
, que anteriormente retornou um tamanho inválido devido o buggyUITextView
Para o iOS 7.0, descobri que o truque contentInset não funciona mais. Este é o código que eu usei para me livrar da margem / preenchimento no iOS 7.
Isso traz a borda esquerda do texto para a borda esquerda do contêiner:
Isso faz com que a parte superior do texto fique alinhada com a parte superior do contêiner
Ambas as linhas são necessárias para remover completamente a margem / preenchimento.
fonte
self.descriptionTextView.textContainerInset = UIEdgeInsetsZero;
lineFragmentPadding
como 0 é a mágica que eu estava procurando. Não sei por que a Apple torna tão difícil alinhar o conteúdo do UITextView com outros controles.lineFragmentPadding
não se destina a modificar margens. A partir dos docs Linha fragmento de preenchimento não é projetado para expressar margens do texto. Em vez disso, você deve usar inserções em sua exibição de texto, ajustar os atributos da margem do parágrafo ou alterar a posição da exibição de texto em sua superview.Esta solução alternativa foi escrita em 2009 quando o IOS 3.0 foi lançado. Não se aplica mais.
Encontrei exatamente o mesmo problema, no final tive que terminar usando
onde nameField é a
UITextView
. A fonte que eu estava usando era Helvetica 16 pontos. É apenas uma solução personalizada para o tamanho de campo específico que eu estava desenhando. Isso faz com que o deslocamento esquerdo fique nivelado com o lado esquerdo, e o deslocamento superior, onde eu quero, para a caixa ser atraída.Além disso, isso parece se aplicar apenas ao
UITextViews
local em que você está usando o alinhamento padrão, ou seja.Alinhar à direita, por exemplo, e o efeito
UIEdgeInsetsMake
parece não ter nenhum impacto na borda direita.No mínimo, o uso da propriedade .contentInset permite colocar seus campos nas posições "corretas" e acomodar os desvios sem compensar o seu
UITextViews
.fonte
Com base em algumas das boas respostas já fornecidas, aqui está uma solução baseada no Storyboard / Interface Builder que funciona no iOS 7.0 ou superior
Defina os Atributos de tempo de execução definidos pelo usuário do UITextView para as seguintes chaves:
fonte
No iOS 5
UIEdgeInsetsMake(-8,-8,-8,-8);
parece funcionar muito bem.fonte
Definitivamente, evitaria respostas com valores codificados, pois as margens reais podem mudar com as configurações de tamanho de fonte do usuário etc.
Aqui está a resposta do @ user1687195, escrita sem modificar o
textContainer.lineFragmentPadding
(porque os documentos afirmam que esse não é o uso pretendido).Isso funciona muito bem para o iOS 7 e posterior.
Este é efetivamente o mesmo resultado, apenas um pouco mais limpo, pois não usa mal a propriedade lineFragmentPadding.
fonte
self.textView.textContainer.lineFragmentPadding = 0;
lineFragmentPadding
não se destina a controlar as margens. É por isso que você deveria usartextContainerInset
.Solução Storyboard ou Interface Builder usando Atributos de Tempo de Execução Definidos pelo Usuário :
As capturas de tela são do iOS 7.1 e iOS 6.1 com
contentInset = {{-10, -5}, {0, 0}}
.fonte
Todas essas respostas abordam a questão do título, mas eu queria propor algumas soluções para os problemas apresentados no corpo da pergunta do OP.
Tamanho do conteúdo do texto
Uma maneira rápida de calcular o tamanho do texto dentro de
UITextView
é usar oNSLayoutManager
:Isso fornece o conteúdo rolável total, que pode ser maior que o
UITextView
quadro do. Achei isso muito mais preciso do que,textView.contentSize
pois calcula quanto espaço o texto ocupa. Por exemplo, dado um vazioUITextView
:Altura da linha
UIFont
possui uma propriedade que permite rapidamente obter a altura da linha para a fonte especificada. Assim, você pode encontrar rapidamente a altura da linha do textoUITextView
com:Cálculo do tamanho do texto visível
Determinar a quantidade de texto realmente visível é importante para manipular um efeito de "paginação".
UITextView
tem uma propriedade chamadatextContainerInset
que na verdade é uma margem entre o realUITextView.frame
e o próprio texto. Para calcular a altura real do quadro visível, você pode executar os seguintes cálculos:Determinando o tamanho da paginação
Por fim, agora que você tem o tamanho do texto visível e o conteúdo, pode determinar rapidamente quais devem ser suas compensações subtraindo o valor
textHeight
detextSize
:Usando todos esses métodos, eu não toquei em minhas inserções e pude ir para o cursor ou para qualquer lugar do texto que desejar.
fonte
você pode usar a
textContainerInset
propriedade deUITextView
:textView.textContainerInset = UIEdgeInsetsMake (10, 10, 10, 10);
(superior, esquerda, inferior, direita)
fonte
textContainerInset
propriedade não está funcionando para mim quando eu quero alterá-lo para um novo valor - consulte stackoverflow.com/questions/19422578/… .Para o iOS 10, a seguinte linha funciona para a remoção de preenchimento superior e inferior.
fonte
UIEdgeInset.zero
funciona usando o XCode 8.3 e o iOS 10.3 SimulatorSwift mais recente:
fonte
Aqui está uma versão atualizada da resposta muito útil de Fattie. Ele adiciona duas linhas importantes que me ajudaram a fazer o layout funcionar no iOS 10 e 11 (e provavelmente nas mais baixas também):
As linhas importantes são as duas
translatesAutoresizingMaskIntoConstraints = <true/false>
declarações!Surpreendentemente, isso remove todas as margens em todas as minhas circunstâncias!
Embora
textView
não seja o primeiro a responder, pode acontecer que haja uma margem inferior estranha que não possa ser resolvida usando osizeThatFits
método mencionado na resposta aceita.Ao tocar no textView de repente, a margem inferior estranha desapareceu e tudo parecia como deveria, mas apenas assim que o textView chegou
firstResponder
.Então, li aqui no SO que ativar e desativar
translatesAutoresizingMaskIntoConstraints
ajuda ao definir o quadro / limites manualmente entre as chamadas.Felizmente, isso não funciona apenas com a configuração de quadro, mas com as 2 linhas de
setup()
sanduíche entre as duastranslatesAutoresizingMaskIntoConstraints
chamadas!Isso, por exemplo, é muito útil ao calcular o quadro de uma vista usando
systemLayoutSizeFitting
aUIView
. Devolve o tamanho correto (o que anteriormente não acontecia)!Como na resposta original mencionada:
Não se esqueça de desativar o scrollEnabled no Inspector!
Essa solução funciona corretamente no storyboard, bem como no tempo de execução.
É isso aí, agora você está realmente pronto!
fonte
Para o swift 4, Xcode 9
Use a seguinte função para alterar a margem / preenchimento do texto no UITextView
então, neste caso, é
fonte
Fazendo a solução inserida, eu ainda tinha preenchimento no lado direito e no fundo. O alinhamento de texto também estava causando problemas. O único caminho certo que encontrei foi colocar a exibição de texto dentro de outra exibição cortada aos limites.
fonte
Aqui está uma pequena extensão fácil que removerá a margem padrão da Apple de todas as visualizações de texto em seu aplicativo.
Nota: O Interface Builder ainda mostrará a margem antiga, mas seu aplicativo funcionará conforme o esperado.
fonte
Para mim (iOS 11 e Xcode 9.4.1), o que funcionou magicamente foi configurar a propriedade textView.font para
UIFont.preferred(forTextStyle:UIFontTextStyle)
estilizar e também a primeira resposta, como mencionado por @Fattie. Mas a resposta @Fattie não funcionou até eu definir a propriedade textView.font, caso contrário o UITextView continua se comportando de maneira irregular.fonte
Caso alguém que esteja procurando pela versão mais recente do Swift, o código abaixo esteja funcionando bem com o Xcode 10.2 e o Swift 4.2
fonte
Eu encontrei mais uma abordagem, obtendo visualização com texto das subvisões do UITextView e configurando-o no método layoutSubview de uma subclasse:
fonte
A rolagem textView também afeta a posição do texto e faz com que pareça não centralizado verticalmente. Consegui centralizar o texto na visualização desativando a rolagem e definindo a inserção superior como 0:
Por alguma razão, ainda não descobri, o cursor ainda não está centralizado antes do início da digitação, mas o texto é centralizado imediatamente quando começo a digitar.
fonte
Caso deseje definir uma string HTML e evitar o preenchimento inferior, verifique se você não está usando tags de bloco, por exemplo, div, p.
No meu caso, esse foi o motivo. Você pode testá-lo facilmente substituindo ocorrências de tags de bloco por tag de extensão.
fonte
Para SwiftUI
Se você está criando seu próprio TextView usando
UIViewRepresentable
e deseja controlar o preenchimento, em suamakeUIView
função, basta:uiTextView.textContainerInset = UIEdgeInsets(top: 10, left: 18, bottom: 0, right: 18)
ou o que você quiser.
fonte
fonte