Comment puis-je trouver le nombre réel nombre de lignes d'une UILabel
après l'avoir initialisée avec une text
et une font
? J'ai défini sa propriété numberOfLines
sur 0
, de sorte qu'il sera étendu au nombre de lignes nécessaires. Mais alors, comment puis-je savoir combien de lignes il a finalement obtenues après avoir défini sa text
?
J'ai trouvé des questions similaires, mais aucune ne semble fournir une réponse concise et il me semble qu'il doit être très facile de l'obtenir sans aucun frais supplémentaire pour jongler avec les boundingRectWithSize
ou sizeWithFont
, ...
Première option:
Tout d'abord, calculez la hauteur du texte en fonction de la police:
NSInteger lineCount = 0;
CGSize labelSize = (CGSize){yourLabel.frame.size.width, MAXFLOAT};
CGRect requiredSize = [self boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: yourLabel.font} context:nil];
Maintenant, calcule le nombre de lignes:
int charSize = lroundf(yourLabel.font.lineHeight);
int rHeight = lroundf(requiredSize.height);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);
Deuxième option :
NSInteger lineCount = 0;
CGSize textSize = CGSizeMake(yourLabel.frame.size.width, MAXFLOAT);
int rHeight = lroundf([yourLabel sizeThatFits:textSize].height);
int charSize = lroundf(yourLabel.font.lineHeight);
lineCount = rHeight/charSize;
NSLog(@"No of lines: %i",lineCount);
Aucun de ceux-ci n'a fonctionné pour moi. Ci-dessous on fait,
Swift 4.2:
extension UILabel {
func calculateMaxLines() -> Int {
let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
let charSize = font.lineHeight
let text = (self.text ?? "") as NSString
let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}
Swift 4/4.1:
extension UILabel {
func calculateMaxLines() -> Int {
let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
let charSize = font.lineHeight
let text = (self.text ?? "") as NSString
let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}
Swift 3:
extension UILabel {
func calculateMaxLines() -> Int {
let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
let charSize = font.lineHeight
let text = (self.text ?? "") as NSString
let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}
Swift 3 (IOS 10.3)
extension UILabel {
var numberOfVisibleLines: Int {
let textSize = CGSize(width: CGFloat(self.frame.size.width), height: CGFloat(MAXFLOAT))
let rHeight: Int = lroundf(Float(self.sizeThatFits(textSize).height))
let charSize: Int = lroundf(Float(self.font.pointSize))
return rHeight / charSize
}
}
Utilisation
print(yourLabel.numberOfVisibleLines)
Voici une version de Swift de la solution @Paresh:
func lines(label: UILabel) -> Int {
let textSize = CGSize(width: label.frame.size.width, height: CGFloat(Float.infinity))
let rHeight = lroundf(Float(label.sizeThatFits(textSize).height))
let charSize = lroundf(Float(label.font.lineHeight))
let lineCount = rHeight/charSize
return lineCount
}
EDIT: Je ne sais pas pourquoi, mais le code renvoie 2 lignes de plus que le nombre réel de lignes. Pour ma solution, je les ai juste soustraites avant de retourner lineCount.
Les autres réponses ici ne respectent pas la propriété numberOfLines
de UILabel
lorsqu'elle est définie sur autre chose que 0.
Voici une autre option que vous pouvez ajouter à votre catégorie ou sous-classe:
- (NSUInteger)lineCount
{
CGSize size = [self sizeThatFits:CGSizeMake(self.frame.size.width, CGFLOAT_MAX)];
return MAX((int)(size.height / self.font.lineHeight), 0);
}
Quelques notes:
font
, et cela fonctionne bien. Évidemment, vous auriez des problèmes si vous utilisiez plusieurs polices dans votre attributedText
.UILabel
pour avoir des incrustations Edge personnalisées (par exemple, en remplaçant drawTextInRect:
, ce qui est une astuce intéressante que j'ai trouvée ici ), vous devez vous rappeler de prendre en compte ces incrustes lors du calcul de size
ci-dessus. Par exemple: CGSizeMake(self.frame.size.width - (self.insets.left + self.insets.right), CGFLOAT_MAX)
Voici le code Swift3 Ici vous pouvez définir la valeur Int et obtenir la hauteur de la taille du texte en utilisant (MAXFLOAT) et en utilisant cette hauteur, vous pouvez obtenir la hauteur totale de UILabel et en la divisant par caractère taille, vous pouvez obtenir le nombre de lignes réel d’UILabel.
var lineCount: Int = 0
var textSize = CGSize(width: CGFloat(yourLabel.frame.size.width), height: CGFloat(MAXFLOAT))
var rHeight: Int = lroundf(yourLabel.sizeThatFits(textSize).height)
var charSize: Int = lroundf(yourLabel.font.leading)
lineCount = rHeight / charSize
print("No of lines: \(lineCount)")
Pour faire suite à la réponse de @ Prince, j’ai maintenant implémenté un category on UILabel
comme suit (notez que j’ai corrigé quelques erreurs de syntaxe mineures dans sa réponse qui ne laissaient pas le code compiler):
#import <UIKit/UIKit.h>
@interface UILabel (Util)
- (NSInteger)lineCount;
@end
#import "UILabel+Util.h"
@implementation UILabel (Util)
- (NSInteger)lineCount
{
// Calculate height text according to font
NSInteger lineCount = 0;
CGSize labelSize = (CGSize){self.frame.size.width, FLT_MAX};
CGRect requiredSize = [self.text boundingRectWithSize:labelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: self.font} context:nil];
// Calculate number of lines
int charSize = self.font.leading;
int rHeight = requiredSize.size.height;
lineCount = rHeight/charSize;
return lineCount;
}
@end
Vous pouvez trouver le nombre total de lignes disponibles dans votre étiquette personnalisée Veuillez vérifier ce code ...
NSInteger numberOfLines = [self lineCountForText:@"YOUR TEXT"];
- (int)lineCountForText:(NSString *) text
{
UIFont *font = [UIFont systemFontOfSize: 15.0];
int width=Your_LabelWidht;
CGRect rect = [text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil];
return ceil(rect.size.height / font.lineHeight);
}
Il semble que le site Web officiel du développeur mentionne une solution Comptage de lignes de texte dans Objc. Toutefois, cela suppose que vous ayez une référence à une vue de texte configurée avec un gestionnaire de disposition, un stockage de texte et un conteneur de texte. Malheureusement, UILabel ne nous les expose pas, nous devons donc les créer avec la même configuration que UILabel.
J'ai traduit le code Objc en Swift comme suit. Cela semble bien fonctionner pour moi.
extension UILabel {
var actualNumberOfLines: Int {
let textStorage = NSTextStorage(attributedString: self.attributedText!)
let layoutManager = NSLayoutManager()
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: self.bounds.size)
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = self.lineBreakMode
layoutManager.addTextContainer(textContainer)
let numberOfGlyphs = layoutManager.numberOfGlyphs
var numberOfLines = 0, index = 0, lineRange = NSMakeRange(0, 1)
while index < numberOfGlyphs {
layoutManager.lineFragmentRect(forGlyphAt: index, effectiveRange: &lineRange)
index = NSMaxRange(lineRange)
numberOfLines += 1
}
return numberOfLines
}
}
let l = UILabel()
l.numberOfLines = 0
l.layer.frame.size.width = self.view.frame.width - 40 /*padding(20 + 20)*/
l.font = UIFont(name: "BwModelica-Bold", size: 16.0)
l.text = "Random Any length Text!!"
let noOfLines = ceil(l.intrinsicContentSize.width) / l.frame.width)
let lbl_height = noOfLines * l.intrinsicContentSize.height
Ce sera votre hauteur dynamique exacte de Label et le nombre de lignes. Bonne codage !!!
Xamarin.iOS
Merci aux réponses fournies par tous ci-dessus.
Cela donne le nombre de lignes visibles.
public static int VisibleLineCount(this UILabel label)
{
var textSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue);
nfloat rHeight = label.SizeThatFits(textSize).Height;
nfloat charSize = label.Font.LineHeight;
return Convert.ToInt32(rHeight / charSize);
}
Cela donne le nombre réel de lignes que le texte occupera à l'écran.
public static int LineCount(this UILabel label)
{
var maxSize = new CGSize(label.Frame.Size.Width, nfloat.MaxValue);
var charSize = label.Font.LineHeight;
var text = (label.Text ?? "").ToNSString();
var textSize = text.GetBoundingRect(maxSize, NSStringDrawingOptions.UsesLineFragmentOrigin, new UIStringAttributes() { Font = label.Font }, null);
return Convert.ToInt32(textSize.Height / charSize);
}
Une méthode d'assistance que je trouve utile pour mon cas d'utilisation.
public static bool IsTextTruncated(this UILabel label)
{
if (label.Lines == 0)
{
return false;
}
return (label.LineCount() > label.Lines);
}
Pour obtenir un nombre de lignes plus précis:
font.lineHeight
au lieu de font.pointSize
Notez que la réponse de @ kurt-j ne fonctionnera pas toujours. Dans certains cas, vous devrez fournir manuellement la largeur de l'étiquette. Étant donné que ces cas existent, il est judicieux d’avoir un paramètre optionnel width, même si vous ne l’utilisez pas.
Swift 4.2:
extension UILabel {
func calculateMaxLines(actualWidth: CGFloat?) -> Int {
var width = frame.size.width
if let actualWidth = actualWidth {
width = actualWidth
}
let maxSize = CGSize(width: width, height: CGFloat(Float.infinity))
let charSize = font.lineHeight
let text = (self.text ?? "") as NSString
let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}