Estou tentando obter o ret para uma string atribuída, mas a chamada boundingRectWithSize não está respeitando o tamanho que eu passo e está retornando um ret com uma altura de linha única em oposição a uma altura grande (é uma string longa). Eu experimentei passando um valor muito grande para a altura e também 0 como no código abaixo, mas o rect retornado é sempre o mesmo.
CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
options:NSStringDrawingUsesDeviceMetrics
context:nil];
Isso está quebrado ou preciso fazer outra coisa para que ele retorne um retângulo para o texto agrupado?
objective-c
nsattributedstring
RunLoop
fonte
fonte
lineBreakMode
?Respostas:
Parece que você não estava fornecendo as opções corretas. Para embalar etiquetas, forneça pelo menos:
Nota: se a largura do texto original for inferior a 300.f, não haverá quebra de linha; verifique se o tamanho do limite está correto; caso contrário, você ainda obterá resultados incorretos.
fonte
ceilf(paragraphRect.size.height)
para que ele seja arredondado. Eu esqueço isso o tempo todo e me pergunto por que minhas etiquetas ainda estão cortadas.boundingRectWithSize:
envolvo meus cálculos em CGRectIntegral (), queCGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers
neste caso arredondará a altura e a largura para garantir que nenhum recorte ocorra se a altura ou largura for um valor fracionário.Por alguma razão, boundingRectWithSize sempre retorna tamanho errado. Eu descobri uma solução. Existe um método para UItextView -sizeThatFits que retorna o tamanho adequado para o conjunto de texto. Portanto, em vez de usar boundingRectWithSize, crie um UITextView, com um quadro aleatório e chame seu sizeThatFits com a respectiva largura e altura CGFLOAT_MAX. Retorna o tamanho que terá a altura adequada.
Se você estiver calculando o tamanho em um loop while, não se esqueça de adicioná-lo em um pool de liberação automática, pois haverá um número n de UITextView criado, a memória do tempo de execução do aplicativo aumentará se não usarmos o recurso de liberação automática.
fonte
UITextView
quantas vezes oheightForRowAtIndexPath
método for chamado? leva tempoEd McManus certamente forneceu uma chave para fazer isso funcionar. Encontrei um caso que não funciona
rect não terá a altura correta. Observe que anotherString (que é anexado à string ) foi inicializado sem um dicionário de atributo. Este é um inicializador legítimo para anotherString, mas boundingRectWithSize: não fornece um tamanho exato nesse caso.
fonte
NSMutableAttributedString
sem atributos e estava obtendo tamanho errado.Minha decisão final após uma longa investigação: a
- boundingRectWithSize
função retorna o tamanho correto apenas para a sequência ininterrupta de caracteres! Caso a string contenha espaços ou algo mais (chamado pela Apple de "Alguns dos glifos") - é impossível obter o tamanho real de rect necessário para exibir o texto!Substituí os espaços nas minhas strings por letras e obtive imediatamente o resultado correto.
A Apple diz aqui: https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize
"Este método retorna os limites reais dos glifos na sequência. É permitido que alguns dos glifos (espaços, por exemplo) se sobreponham às restrições de layout especificadas pelo tamanho passado, portanto, em alguns casos, o valor da largura do componente de tamanho de o retorno
CGRect
pode exceder o valor da largura do parâmetro size ".Portanto, é necessário encontrar outra maneira de calcular o retângulo real ...
Após um longo processo de investigação, a solução finalmente foi encontrada !!! Não tenho certeza de que funcionará bem em todos os casos relacionados
UITextView
, mas foi detectado o principal e o importante!boundingRectWithSize
A função, assim comoCTFramesetterSuggestFrameSizeWithConstraints
(e muitos outros métodos), calculará o tamanho e a parte do texto corretos quando o retângulo correto for usado. Por exemplo -UITextView
hastextView.bounds.size.width
- e esse valor não é um retângulo real usado pelo sistema ao desenhar o textoUITextView
.Achei um parâmetro muito interessante e realizei um cálculo simples no código:
E obras mágicas - todos os meus textos calculados estão corretos agora! Aproveitar!
fonte
Swift four version
A medição do texto com o CTFramesetter funciona melhor, pois fornece tamanhos inteiros e manipula bem os emoji e outros caracteres unicode.
fonte
Não tive sorte com nenhuma dessas sugestões. Minha string continha pontos de marcador unicode e eu suspeito que eles estavam causando sofrimento no cálculo. Percebi que o UITextView estava lidando bem com o desenho, então procurei aproveitar esse cálculo. Fiz o seguinte, que provavelmente não é tão ideal quanto os métodos de desenho NSString, mas pelo menos é preciso. Também é um pouco mais ideal do que inicializar um UITextView apenas para chamar
-sizeThatFits:
.fonte
Caso você queira obter uma caixa delimitadora truncando a cauda, esta pergunta pode ajudá-lo.
fonte
Acontece que TODAS as partes de um NSAttributedString devem ter um dicionário definido com pelo menos NSFontAttributeName e NSForegroundColorAttributeName, se você desejar que boundingRectWithSize realmente funcione!
Não vejo isso documentado em lugar algum.
fonte
@warrenm Lamento dizer que o método do framesetter não funcionou para mim.
Esta função pode nos ajudar a determinar o tamanho do quadro necessário para um intervalo de cadeias de caracteres de um NSAttributedString no iphone / Ipad SDK para uma determinada largura:
Pode ser usado para uma altura dinâmica de células UITableView
Agradecimentos a HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html
fonte
#import <CoreText/CoreText.h>
Descobri que a solução preferida não lida com quebras de linha.
Eu descobri que essa abordagem funciona em todos os casos:
fonte
Eu tive o mesmo problema ao não obter um tamanho exato usando essas técnicas e mudei minha abordagem para fazê-la funcionar.
Eu tenho uma longa seqüência de caracteres atribuída que eu tenho tentado ajustar em uma exibição de rolagem para que ela seja exibida corretamente sem ser truncada. O que fiz para fazer o texto funcionar de maneira confiável foi não definir a altura como uma restrição e, em vez disso, permitir que o tamanho intrínseco assumisse o controle. Agora o texto é exibido corretamente sem ser truncado e não preciso calcular a altura.
Suponho que, se eu precisasse obter a altura de forma confiável, criaria uma exibição oculta e essas restrições e obteria a altura do quadro depois que as restrições fossem aplicadas.
fonte
Estou um pouco atrasado para o jogo - mas tenho tentado descobrir uma maneira que funcione para encontrar a caixa delimitadora que caiba em torno de uma sequência atribuída para fazer um foco soar como a edição de um arquivo no Finder. tudo o que eu tentei falhou quando há espaços no final da string ou vários espaços dentro da string.
boundingRectWithSize
falha miseravelmente por isso e tambémCTFramesetterCreateWithAttributedString
.Usar um
NSLayoutManager
código a seguir parece fazer o truque em todos os casos que encontrei até agora e retorna um ret que limita perfeitamente a string. Bônus: se você selecionar o texto, as bordas da seleção vão até os limites do retângulo retornado. O código abaixo usa o layoutManager de aNSTextView
.fonte
Funciona perfeitamente em todas as fontes!
fonte
Eu tive o mesmo problema, mas reconheci que a restrição de altura foi definida corretamente. Então eu fiz o seguinte:
fonte
Eu tentei de tudo nesta página e ainda tinha um caso para um UILabel que não estava formatando corretamente. A definição do atributoText na etiqueta finalmente resolveu o problema.
fonte
Uma coisa que eu estava notando é que o retângulo que retornaria
(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
teria uma largura maior do que a que passei. Quando isso acontecesse, minha corda seria truncada. Eu resolvi assim:Para um pouco mais de contexto; Eu tinha texto com várias linhas e estava tentando encontrar a altura certa para exibi-lo. BoundRectWithSize às vezes retornava uma largura maior do que o que eu especificaria, portanto, quando eu usava meu passado em largura e a altura calculada para exibir meu texto, ele truncaria. Nos testes, quando boundingRectWithSize usava a largura errada, a quantidade que tornaria a altura menor era de 1 linha. Portanto, eu verificaria se a largura era maior e, em caso afirmativo, adicione o lineHeight da fonte para fornecer espaço suficiente para evitar o truncamento.
fonte
se o quadro da etiqueta não adicionar 10, esse método nunca funcionará! espero que isso possa ajudá-lo! Boa sorte.
fonte
}
fonte
Gostaria de acrescentar meus pensamentos, já que tive exatamente o mesmo problema.
Eu estava usando,
UITextView
pois tinha um alinhamento de texto melhor (justifique, que no momento não estava disponívelUILabel
), mas para "simular" não interativo-não-rolávelUILabel
, eu desativaria completamente a interação de rolagem, salto e interação do usuário .Obviamente, o problema era que o texto era dinâmico e, embora a largura fosse fixa, a altura deveria ser recalculada toda vez que eu definir um novo valor de texto.
boundingRectWithSize
não funcionou bem para mim, pelo que pude ver,UITextView
estava adicionando uma margem na parte superior queboundingRectWithSize
não entrava em contagem, portanto, a altura recuperadaboundingRectWithSize
era menor do que deveria.Como o texto não deveria ser atualizado rapidamente, ele é usado apenas para algumas informações que podem ser atualizadas a cada 2-3 segundos, decidi a seguinte abordagem:
* O código acima não é copiado diretamente da minha fonte, eu tive que ajustá-lo / limpá-lo de várias outras coisas não necessárias para este artigo. Não aceite o código copiar-colar-e-ele-funcionará.
A desvantagem óbvia é que ele tem alocação e liberação para cada chamada.
Mas, a vantagem é que você evite dependendo da compatibilidade entre a forma como boundingRectWithSize desenha texto e calcula o seu tamanho e implementação de desenho de texto em
UITextView
(ouUILabel
o que também é possível utilizar apenas substituirUITextView
comUILabel
). Quaisquer "bugs" que a Apple possa ter são assim evitados.PS: Parece que você não precisa desse "temp"
UITextView
e pode apenas perguntarsizeThatFits
diretamente do alvo, mas isso não funcionou para mim. Embora a lógica diga que deve funcionar e que a alocação / liberação temporáriaUITextView
não é necessária, ela não funcionou. Mas essa solução funcionou perfeitamente para qualquer texto que eu inserisse.fonte
Ok, então eu passei muito tempo depurando isso. Descobri que a altura máxima do texto, conforme definida pela
boundingRectWithSize
permissão para exibir texto por minha,UITextView
era menor que o tamanho do quadro.No meu caso, o quadro é no máximo 140pt, mas o UITextView tolera no máximo 131pt.
Eu tive que descobrir isso manualmente e codificar a altura máxima "real".
Aqui está a minha solução:
fonte