J'ai vu plusieurs exemples pour changer la taille d'un UILabel.
Voici ce que j'aimerais faire : Modifier la taille de la police pour que le texte soit aussi grand que possible dans la nouvelle hauteur.
Des indications ?
J'ai vu plusieurs exemples pour changer la taille d'un UILabel.
Voici ce que j'aimerais faire : Modifier la taille de la police pour que le texte soit aussi grand que possible dans la nouvelle hauteur.
Des indications ?
J'ai eu exactement le même problème et, grâce à ce fil et à l'algorithme de Joel, j'ai pu le résoudre. :-)
Voici mon code en Swift. Je suis sur iOS 8 + Autolayout.
Problème:
Après la correction :
C'est exactement ce que le designer avait en tête... :)
J'ai sous-classé UILabel et j'ai remplacé layoutSubviews
. Ensuite, à chaque fois que la taille du UILabel est modifiée, la taille de la police est recalculée :
//
// LabelWithAdaptiveTextHeight.swift
// 123
//
// Créé par https://github.com/backslash-f le 19/12/14.
//
/*
Conçu en pensant aux UILabels à une seule ligne, cette sous-classe 'redimensionne' le texte de l'étiquette (elle modifie la taille de la police de l'étiquette)
à chaque fois que sa taille (frame) est modifiée. Cela 'ajuste' le texte à la nouvelle hauteur, évitant ainsi le rognage du texte.
Félicitations à ce fil de discussion Stack Overflow : bit.ly/setFontSizeToFillUILabelHeight
*/
import Foundation
import UIKit
class LabelWithAdaptiveTextHeight: UILabel {
override func layoutSubviews() {
super.layoutSubviews()
font = fontToFitHeight()
}
// Renvoie une UIFont qui s'adapte à la nouvelle hauteur de l'étiquette.
private func fontToFitHeight() -> UIFont {
var minFontSize: CGFloat = DISPLAY_FONT_MINIMUM // CGFloat 18
var maxFontSize: CGFloat = DISPLAY_FONT_BIG // CGFloat 67
var fontSizeAverage: CGFloat = 0
var textAndLabelHeightDiff: CGFloat = 0
while (minFontSize <= maxFontSize) {
fontSizeAverage = minFontSize + (maxFontSize - minFontSize) / 2
// Abandonner si le texte s'avère être nil
guard text?.characters.count > 0 else {
break
}
if let labelText: NSString = text {
let labelHeight = frame.size.height
let testStringHeight = labelText.sizeWithAttributes(
[NSFontAttributeName: font.fontWithSize(fontSizeAverage)]
).height
textAndLabelHeightDiff = labelHeight - testStringHeight
if (fontSizeAverage == minFontSize || fontSizeAverage == maxFontSize) {
if (textAndLabelHeightDiff < 0) {
return font.fontWithSize(fontSizeAverage - 1)
}
return font.fontWithSize(fontSizeAverage)
}
if (textAndLabelHeightDiff < 0) {
maxFontSize = fontSizeAverage - 1
} else if (textAndLabelHeightDiff > 0) {
minFontSize = fontSizeAverage + 1
} else {
return font.fontWithSize(fontSizeAverage)
}
}
}
return font.fontWithSize(fontSizeAverage)
}
}
Il y a une solution plus simple. Il suffit d'ajouter les lignes ci-dessous et comme par magie, l'étiquette ajuste sa taille de police pour s'adapter à la hauteur de l'étiquette également :
SWIFT 3 :
label.minimumScaleFactor = 0.1 //ou tout ce qui convient à vos besoins
label.adjustsFontSizeToFitWidth = true
label.lineBreakMode = .byClipping
label.numberOfLines = 0
Voici comment j'ai fait, car la réponse de DGund ne fonctionnait pas pour moi, elle convenait à la largeur, mais je voulais qu'elle s'adapte à la hauteur.
+ (UIFont *)findAdaptiveFontWithName:(NSString *)fontName forUILabelSize:(CGSize)labelSize withMinimumSize:(NSInteger)minSize
{
UIFont *tempFont = nil;
NSString *testString = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
NSInteger tempMin = minSize;
NSInteger tempMax = 256;
NSInteger mid = 0;
NSInteger difference = 0;
while (tempMin <= tempMax) {
mid = tempMin + (tempMax - tempMin) / 2;
tempFont = [UIFont fontWithName:fontName size:mid];
difference = labelSize.height - [testString sizeWithFont:tempFont].height;
if (mid == tempMin || mid == tempMax) {
if (difference < 0) {
return [UIFont fontWithName:fontName size:(mid - 1)];
}
return [UIFont fontWithName:fontName size:mid];
}
if (difference < 0) {
tempMax = mid - 1;
} else if (difference > 0) {
tempMin = mid + 1;
} else {
return [UIFont fontWithName:fontName size:mid];
}
}
return [UIFont fontWithName:fontName size:mid];
}
Cela prendra un nom de police, une taille (cela ne doit pas nécessairement être un UILabel, théoriquement, mais je l'ai toujours utilisé avec un UILabel), et une taille minimum (vous pourriez également utiliser une taille maximum, remplacez simplement le 256 par le paramètre de taille maximum). Cela testera essentiellement chaque taille de police entre la taille minimale et maximale de la police et renverra celle qui est à ou juste en dessous de la hauteur cible.
L'utilisation est explicite, mais ressemble à ceci :
self.myLabel.font = [self findAdaptiveFontWithName:@"HelveticaNeue-UltraLight" forUILabelSize:self.myLabel.frame.size withMinimumSize:30];
Vous pouvez également en faire une méthode de classe sur UIFont (c'est ce que j'ai fait).
ÉDITER : Suite à une suggestion, j'ai supprimé la boucle for et ai passé un peu de temps à le rendre plus efficace avec une routine de recherche binaire. J'ai effectué plusieurs vérifications pour m'assurer absolument que la police finira par s'adapter dans le label. Lors de tests initiaux, cela semble fonctionner.
Éditer: Consultez la superbe réponse de Joel Fischer pour obtenir la taille correcte de manière programmatique!
Vous pouvez définir la police pour remplir automatiquement la taille d'une étiquette, et éventuellement ne pas descendre en dessous d'une taille de police minimale. Il suffit de définir adjustsFontSizeToFitWidth
sur OUI.
Consultez la Référence de la classe UILabel si vous avez besoin de plus d'informations.
Bien que le booléen s'appelle "adjustsFontSizeToFitWidth," cela signifie vraiment la plus grande taille pour la hauteur de l'étiquette, qui restera sur une seule ligne de l'étiquette (ou sur autant de lignes que vous spécifiez).
Pour adapter le texte en fonction de la hauteur de mon libellé, j'ai adapté la méthode de Joel à Swift
func optimisedfindAdaptiveFontWithName(fontName:String, label:UILabel!, minSize:CGFloat,maxSize:CGFloat) -> UIFont!
{
var tempFont:UIFont
var tempHeight:CGFloat
var tempMax:CGFloat = maxSize
var tempMin:CGFloat = minSize
while (ceil(tempMin) != ceil(tempMax)){
let testedSize = (tempMax + tempMin) / 2
tempFont = UIFont(name:fontName, size:testedSize)
let attributedString = NSAttributedString(string: label.text!, attributes: [NSFontAttributeName : tempFont])
let textFrame = attributedString.boundingRectWithSize(CGSize(width: label.bounds.size.width, height: CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin , context: nil)
let difference = label.frame.height - textFrame.height
println("\(tempMin)-\(tempMax) - testé : \(testedSize) --> différence : \(difference)")
if(difference > 0){
tempMin = testedSize
}else{
tempMax = testedSize
}
}
//retourner la taille -1 (pour avoir assez d'espace à droite et à gauche)
return UIFont(name: fontName, size: tempMin - 1)
}
et je l'utilise de cette manière :
myLabel.font = optimisedfindAdaptiveFontWithName("Helvetica", label: myLabel, minSize: 10, maxSize: 38)
println("\(myLabel.font)")
J'ai réussi à le faire fonctionner de manière impressionnante, sauf lorsque j'utilise des lettres minuscules. Parfois, elles sont juste en dehors du cadre de mon étiquette :<
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
1 votes
Je viens de réaliser que réaliser une recherche binaire ou autre est totalement inutile. Vous n'avez qu'à itérer (quelques fois) en utilisant une recherche de ratio. C'est tout simple. Je vais coller le code complet dans ma réponse.
1 votes
.. solution complète pour 2016 stackoverflow.com/a/37277874/294884 Code très simple.