J'essaie d'obtenir le rect pour une chaîne attribuée, mais l'appel boundingRectWithSize ne respecte pas la taille que je passe et renvoie un rect avec une seule hauteur de ligne par opposition à une grande hauteur (c'est une longue chaîne). J'ai expérimenté en passant une très grande valeur pour la hauteur et aussi 0 comme dans le code ci-dessous, mais le rect renvoyé est toujours le même.
CGRect paragraphRect = [attributedText boundingRectWithSize:CGSizeMake(300,0.0)
options:NSStringDrawingUsesDeviceMetrics
context:nil];
Est-ce cassé ou dois-je faire autre chose pour qu'il renvoie un rect pour le texte enveloppé?
objective-c
nsattributedstring
RunLoop
la source
la source
lineBreakMode
?Réponses:
Il semble que vous ne fournissiez pas les bonnes options. Pour emballer les étiquettes, fournissez au moins:
Remarque: si la largeur du texte d'origine est inférieure à 300 f, il n'y aura pas de retour à la ligne, alors assurez-vous que la taille reliée est correcte, sinon vous obtiendrez toujours des résultats erronés.
la source
ceilf(paragraphRect.size.height)
pour qu'il arrondisse. J'oublie cela tout le temps et je me demande pourquoi mes étiquettes sont toujours coupées.boundingRectWithSize:
J'emballe toujours mes calculs dans CGRectIntegral () quiCGRectIntegral rounds the rectangle’s origin downward and its size upward to the nearest whole integers
, dans ce cas, arrondira la hauteur et la largeur pour garantir qu'aucun écrêtage ne se produit si la hauteur ou la largeur est une valeur fractionnaire.Pour une raison quelconque, boundingRectWithSize renvoie toujours une taille incorrecte. J'ai trouvé une solution. Il existe une méthode pour UItextView -sizeThatFits qui renvoie la taille appropriée pour l'ensemble de texte. Ainsi, au lieu d'utiliser boundingRectWithSize, créez un UITextView, avec un cadre aléatoire, et appelez son sizeThatFits avec la largeur et la hauteur CGFLOAT_MAX respectives. Il renvoie la taille qui aura la bonne hauteur.
Si vous calculez la taille dans une boucle while, n'oubliez pas d'ajouter cela dans un pool de libération automatique, car il y aura n nombre d'UITextView créé, la mémoire d'exécution de l'application augmentera si nous n'utilisons pas autoreleasepool.
la source
UITextView
autant de fois que laheightForRowAtIndexPath
méthode est appelée? il faut du tempsEd McManus a certainement fourni une clé pour que cela fonctionne. J'ai trouvé un cas qui ne fonctionne pas
rect n'aura pas la bonne hauteur. Notez qu'une autre chaîne (qui est ajoutée à la chaîne ) a été initialisée sans dictionnaire d'attributs. Il s'agit d'un initialiseur légitime pour anotherString mais boundingRectWithSize: ne donne pas une taille précise dans ce cas.
la source
NSMutableAttributedString
sans attributs et je me trompais de taille.Ma décision finale après une longue enquête: la
- boundingRectWithSize
fonction renvoie la taille correcte pour une séquence ininterrompue de caractères uniquement! Dans le cas où la chaîne contient des espaces ou autre chose (appelé par Apple "Certains des glyphes") - il est impossible d'obtenir la taille réelle du rect nécessaire pour afficher le texte!J'ai remplacé les espaces dans mes chaînes par des lettres et j'ai immédiatement obtenu un résultat correct.
Apple dit ici: https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrectwithsize
"Cette méthode renvoie les limites réelles des glyphes dans la chaîne. Certains des glyphes (espaces, par exemple) sont autorisés à chevaucher les contraintes de mise en page spécifiées par la taille transmise, donc dans certains cas, la valeur de largeur du composant de taille de la valeur renvoyée
CGRect
peut dépasser la valeur de largeur du paramètre de taille. "Il est donc nécessaire de trouver un autre moyen de calculer le droit réel ...
Après un long processus d'enquête, la solution a finalement été trouvée !!! Je ne suis pas sûr que cela fonctionnera bien pour tous les cas liés à
UITextView
, mais la chose principale et importante a été détectée!boundingRectWithSize
function ainsi queCTFramesetterSuggestFrameSizeWithConstraints
(et de nombreuses autres méthodes) calculera la taille et la partie de texte correctement lorsque le rectangle correct est utilisé. Par exemple -UITextView
atextView.bounds.size.width
- et cette valeur n'est pas un rectangle réel utilisé par le système lors du dessin de texteUITextView
.J'ai trouvé un paramètre très intéressant et effectué un calcul simple en code:
Et la magie fonctionne - tous mes textes calculés correctement maintenant! Prendre plaisir!
la source
Version Swift quatre
Mesurer le texte avec CTFramesetter fonctionne mieux car il fournit des tailles entières et gère bien les emoji et autres caractères Unicode.
la source
Je n'ai eu de chance avec aucune de ces suggestions. Ma chaîne contenait des puces Unicode et je soupçonne qu'elles causaient des problèmes dans le calcul. J'ai remarqué que UITextView gérait bien le dessin, alors j'ai cherché à tirer parti de son calcul. J'ai fait ce qui suit, ce qui n'est probablement pas aussi optimal que les méthodes de dessin NSString, mais au moins c'est précis. C'est aussi légèrement plus optimal que d'initialiser un UITextView juste pour appeler
-sizeThatFits:
.la source
Si vous souhaitez obtenir un cadre de délimitation en tronquant la queue, cette question peut vous aider.
la source
Il s'avère que CHAQUE partie d'un NSAttributedString doit avoir un dictionnaire défini avec au moins NSFontAttributeName et NSForegroundColorAttributeName définis, si vous souhaitez que boundingRectWithSize fonctionne réellement!
Je ne vois cela documenté nulle part.
la source
@warrenm Désolé de dire que la méthode du framesetter n'a pas fonctionné pour moi.
Cette fonction peut nous aider à déterminer la taille de trame nécessaire pour une plage de chaînes d'un NSAttributedString dans le SDK iphone / Ipad pour une largeur donnée:
Il peut être utilisé pour une hauteur dynamique de cellules UITableView
Merci à HADDAD ISSA >>> http://haddadissa.blogspot.in/2010/09/compute-needed-heigh-for-fixed-width-of.html
la source
#import <CoreText/CoreText.h>
J'ai constaté que la solution préférée ne gère pas les sauts de ligne.
J'ai trouvé que cette approche fonctionne dans tous les cas:
la source
J'ai eu le même problème de ne pas obtenir une taille précise en utilisant ces techniques et j'ai changé mon approche pour que cela fonctionne.
J'ai une longue chaîne attribuée que j'ai essayé d'intégrer dans une vue de défilement afin qu'elle s'affiche correctement sans être tronquée. Ce que j'ai fait pour que le texte fonctionne de manière fiable, c'est de ne pas définir du tout la hauteur comme contrainte et de laisser la taille intrinsèque prendre le dessus. Maintenant, le texte s'affiche correctement sans être tronqué et je n'ai pas à calculer la hauteur.
Je suppose que si j'avais besoin d'obtenir la hauteur de manière fiable, je créerais une vue cachée et ces contraintes et obtiendrais la hauteur du cadre une fois les contraintes appliquées.
la source
Je suis un peu en retard dans le jeu - mais j'ai essayé de trouver un moyen qui fonctionne pour trouver la boîte englobante qui s'adaptera autour d'une chaîne attribuée pour faire un anneau de mise au point comme le fait l'édition d'un fichier dans Finder. tout ce que j'avais essayé a échoué lorsqu'il y a des espaces à la fin de la chaîne ou plusieurs espaces à l'intérieur de la chaîne.
boundingRectWithSize
échoue lamentablement pour cela ainsi queCTFramesetterCreateWithAttributedString
.L'utilisation d'un
NSLayoutManager
code suivant semble faire l'affaire dans tous les cas que j'ai trouvés jusqu'à présent et renvoie un rect qui délimite parfaitement la chaîne. Bonus: si vous sélectionnez le texte les bords de la sélection remontent jusqu'aux limites du rect renvoyé. Le code ci-dessous utilise le layoutManager d'un fichierNSTextView
.la source
Fonctionne parfaitement sur toutes les polices!
la source
J'ai eu le même problème, mais j'ai reconnu que la hauteur contrainte a été réglée correctement. J'ai donc fait ce qui suit:
la source
J'ai tout essayé sur cette page et j'avais encore un cas pour un UILabel qui ne se formait pas correctement. En fait, la définition du texte attribué sur l'étiquette a finalement résolu le problème.
la source
Une chose que je remarquais, c'est que le rect qui reviendrait
(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
aurait une largeur plus grande que ce que j'ai passé. Quand cela se produisait, ma chaîne serait tronquée. Je l'ai résolu comme ceci:Pour un peu plus de contexte; J'avais du texte sur plusieurs lignes et j'essayais de trouver la bonne hauteur pour l'afficher. BoundRectWithSize renvoyait parfois une largeur plus grande que ce que je spécifierais, donc quand j'utilisais mon passé en largeur et la hauteur calculée pour afficher mon texte, il tronquerait. À partir du test lorsque boundingRectWithSize a utilisé une largeur incorrecte, la valeur de réduction de la hauteur était de 1 ligne. Je vérifierais donc si la largeur était plus grande et si tel était le cas, ajouterais lineHeight de la police pour fournir suffisamment d'espace pour éviter la troncature.
la source
si le cadre de l'étiquette n'ajoute pas 10, cette méthode ne fonctionnera jamais! j'espère que cela peut vous aider! bonne chance.
la source
}
la source
Je voudrais ajouter mes réflexions car j'avais exactement le même problème.
J'utilisais
UITextView
car il avait un meilleur alignement du texte (justifiez, qui à l'époque n'était pas disponible dansUILabel
), mais afin de "simuler" non-interactif-non-défilableUILabel
, je désactivais complètement le défilement, le rebond et l'interaction de l'utilisateur .Bien sûr, le problème était que le texte était dynamique et, bien que la largeur soit fixe, la hauteur devrait être recalculée chaque fois que je définissais une nouvelle valeur de texte.
boundingRectWithSize
Cela ne fonctionnait pas du tout pour moi, d'après ce que je pouvais voir,UITextView
ajoutait une marge sur le dessus quiboundingRectWithSize
n'entrerait pas dans un décompte, par conséquent, la hauteur récupéréeboundingRectWithSize
était plus petite qu'elle ne devrait l'être.Étant donné que le texte ne devait pas être mis à jour rapidement, il est simplement utilisé pour certaines informations qui peuvent être mises à jour toutes les 2-3 secondes au maximum, j'ai décidé de l'approche suivante:
* Le code ci-dessus n'est pas directement copié à partir de ma source, j'ai dû l'ajuster / le supprimer d'un tas d'autres éléments non nécessaires pour cet article. Ne le prenez pas pour copier-coller-et-cela-fonctionnera-code.
L'inconvénient évident est qu'il a l'allocation et la libération, pour chaque appel.
Mais l'avantage est que vous évitez de dépendre de la compatibilité entre la façon dont boundingRectWithSize dessine le texte et calcule sa taille et l'implémentation du dessin de texte dans
UITextView
(ouUILabel
que vous pouvez également utiliser simplement remplacerUITextView
parUILabel
). Tous les «bogues» qu'Apple pourrait avoir sont ainsi évités.PS Il semblerait que vous ne devriez pas avoir besoin de ce "temp"
UITextView
et que vous pouvez simplement demandersizeThatFits
directement à la cible, mais cela n'a pas fonctionné pour moi. Bien que la logique dirait que cela devrait fonctionner et que l'allocation / la libération de temporairesUITextView
ne sont pas nécessaires, ce n'est pas le cas. Mais cette solution fonctionnait parfaitement pour tout texte que je mettrais en place.la source
Ok donc j'ai passé beaucoup de temps à déboguer ça. J'ai découvert que la hauteur maximale du texte telle que définie par
boundingRectWithSize
autorisé à afficher le texte par myUITextView
était inférieure à la taille du cadre.Dans mon cas, le cadre est au plus 140pt mais l'UITextView tolère les textes au maximum 131pt.
J'ai dû comprendre cela manuellement et coder en dur la hauteur maximale «réelle».
Voici ma solution:
la source