Taille de police personnalisée dans les Classes de taille XCode6 ne fonctionne pas correctement avec les polices personnalisées
Xcode 6 a une nouvelle fonctionnalité où les polices et les tailles de police dans UILabel, UITextField, et UIButton peuvent être réglées automatiquement en fonction de la classe de taille de la configuration actuelle de l'appareil, à droite dans le storyboard. Par exemple, vous pouvez définir un UILabel pour utiliser la taille de police 12 sur "n'importe quelle largeur, hauteur compacte" (comme sur les iPhones dans le paysage) configurations et la taille 18 sur "Largeur régulière, hauteur régulière" configurations (comme sur les iPads). Plus d'informations sont disponibles ici:
c'est une très bonne caractéristique en théorie parce qu'elle pourrait rendre inutile de programmer différentes polices sur les caractéristiques de L'interface utilisateur en fonction de la configuration de l'appareil. Maintenant, j'ai quelques conditionnelle code qui définit les polices en fonction du type d'appareil, mais, évidemment, cela signifie que je dois mettre les polices par programmation partout dans l'application. Au départ, j'étais très excité par cette fonctionnalité, mais j'ai découvert qu'elle avait un sérieux problème d'utilisation pour moi (peut-être un bug). Notez que je m'appuie sur le SDK 8 et que je fixe un objectif de déploiement minimum de iOS 8, donc cela n'a rien à voir avec la compatibilité avec les anciennes versions de iOS.
le problème est ce: Si je mets différentes tailles de police pour différentes classes de taille et que j'utilise la police "système" fournie par iOS, tout fonctionne comme suit: attendus et les tailles de police varient selon la taille de la classe. Si j'utilise une police personnalisée fournie par mon application (oui, je l'ai correctement configurée dans mon paquet d'application, car elle fonctionne de manière programmatique) et que je place la police personnalisée sur une étiquette dans un storyboard XCode 6, cela fonctionne aussi comme prévu. Mais quand j'essaie d'utiliser des tailles différentes de la police personnalisée pour différentes classes de taille, dans le storyboard, ça ne marche pas du tout. La seule différence dans la configuration est la police que j'ai choisie (une sur mesure vs. le Système de la police). Au lieu de cela, toutes les polices apparaissent sur le périphérique et le simulateur comme la police système par défaut à la taille par défaut, quelle que soit la classe de taille (et j'ai vérifié par l'intermédiaire du débogueur qu'il remplace la police système actuelle spécifiée dans le storyboard). Donc, en gros, la fonctionnalité de classe de taille semble être cassée pour les polices personnalisées. De plus, il est intéressant de noter que les polices personnalisées affichent et ajustent correctement la taille dans le volet "Preview" de XCode 6 pour le contrôleur de vue: lorsque le système iOS tourne, il cesse de fonctionner (ce qui me fait penser que je le configure correctement).
j'ai essayé plusieurs polices différentes et cela ne semble pas fonctionner pour aucune d'entre elles, mais cela fonctionne toujours si j'utilise" Système " à la place.
est-ce que quelqu'un d'autre a vu ce problème dans Xcode 6? Une idée pour savoir si c'est un bug dans iOS 8, Xcode, ou quelque chose que je fais de travers? La seule solution que j'ai trouvée, comme je l'ai dit, est de continuez à programmer les polices comme je l'ai été pour environ 3 versions de iOS, parce que cela fonctionne. Mais j'aimerais pouvoir utiliser cette fonctionnalité si je pouvais la faire fonctionner avec des polices personnalisées. L'utilisation de la police système n'est pas acceptable pour notre conception.
INFORMATIONS SUPPLÉMENTAIRES: À partir de Xcode 8.0, le bug est corrigé.
14 réponses
Rapide corrigé:
1 )Définir les polices comme système pour les classes de taille
2) sous-classe UILabel et remplacer "layoutSubviews" méthode du type:
- (void)layoutSubviews
{
[super layoutSubviews];
// Implement font logic depending on screen size
if ([self.font.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location == NSNotFound) {
NSLog(@"font is not bold");
self.font = [UIFont fontWithName:@"Custom regular Font" size:self.font.pointSize];
} else {
NSLog(@"font is bold");
self.font = [UIFont fontWithName:@"Custom bold Font" size:self.font.pointSize];
}
}
soit dit en passant, c'est une technique très commode pour les polices iconiques
après avoir tout essayé, je me suis finalement fixé sur une combinaison des solutions ci-dessus. En Utilisant Le Xcode 7.2, Swift 2.
import UIKit
class LabelDeviceClass : UILabel {
@IBInspectable var iPhoneSize:CGFloat = 0 {
didSet {
if isPhone() {
overrideFontSize(iPhoneSize)
}
}
}
@IBInspectable var iPadSize:CGFloat = 0 {
didSet {
if isPad() {
overrideFontSize(iPadSize)
}
}
}
func isPhone() -> Bool {
// return UIDevice.currentDevice().userInterfaceIdiom == .Phone
return !isPad()
}
func isPad() -> Bool {
// return UIDevice.currentDevice().userInterfaceIdiom == .Pad
switch (UIScreen.mainScreen().traitCollection.horizontalSizeClass, UIScreen.mainScreen().traitCollection.verticalSizeClass) {
case (.Regular, .Regular):
return true
default:
return false
}
}
func overrideFontSize(fontSize:CGFloat){
let currentFontName = self.font.fontName
if let calculatedFont = UIFont(name: currentFontName, size: fontSize) {
self.font = calculatedFont
}
}
}
-
@IBInspectable
vous permet de définir la taille de la police dans le Storyboard - il utilise un observateur
didSet
, pour éviter les pièges delayoutSubviews()
(boucle infinie pour les hauteurs dynamiques de la table) etawakeFromNib()
(voir le commentaire de @cocoaNoob) - il utilise des classes de taille plutôt que l'idiome de l'appareil, dans l'espoir d'utiliser éventuellement ce avec
@IBDesignable
- Malheureusement,
@IBDesignable
ne fonctionne pas avectraitCollection
, selon cet autre "1519200920 pile" article - la déclaration de l'interrupteur de collecte de trait est effectuée sur
UIScreen.mainScreen()
plutôt queself
par ce article de pile
solution de contournement pour UILabel
: conserver la même taille de police sur toutes les classes de taille, mais changer la hauteur de votre étiquette en conséquence dans chaque classe de taille. Votre étiquette doit avoir autoshrink activé. Il a travaillé très bien l'affaire dans mon cas.
ce bug (et d'autres Classes de taille de Xcode) m'a causé de sérieux ennuis récemment car j'ai dû passer par un énorme hacking de fichier storyboard.
pour toute autre personne dans cette position, j'aimerais ajouter quelque chose en plus de la réponse de @razor28 pour soulager la douleur.
dans le fichier d'en-tête de votre sous-classe personnalisée, utilisez IBInspectable
pour vos attributs d'exécution. Cela rendra ces attributs accessibles à partir de "L'Inspecteur des attributs"", visuellement juste au-dessus de la position par défaut pour les paramètres de police.
exemple d'utilisation:
@interface MyCustomLabel : UILabel
@property (nonatomic) IBInspectable NSString *fontType;
@property (nonatomic) IBInspectable CGFloat iphoneFontSize;
@property (nonatomic) IBInspectable CGFloat ipadFontSize;
@end
cela va très utilement produire cette sortie:
un avantage supplémentaire est que maintenant nous n'avons pas à ajouter les attributs runtime manuellement pour chaque étiquette. C'est le plus proche que J'ai pu obtenir du comportement prévu de XCode. Avec un peu de chance, iOS 9 est en route cet été.
solution similaire à celle de @razor28 mais je pense un peu plus universelle. Aussi, fonctionne très bien sur les versions iOS plus anciennes
le bogue est toujours valide dans XCode 7.0 GM.
la solution de Razor28 provoque des boucles infinies dans certains cas. Mon expérience a été de l'utiliser en conjonction avec SwipeView .
à la place, je vous suggère:
1) sous-classe UILabel et remplacer setFont:
- (void)setFont:(UIFont *)font
{
font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize];
[super setFont:font];
}
2) définir la classe personnalisée de vos UILabels et ensuite définissez les classes de taille de police en utilisant la police système
le problème est toujours là que vous ne pouvez pas utiliser la fonctionnalité pour définir des polices pour différentes classes de taille de interface builder.
Juste définir la police en fonction de l'appareil que vous voulez comme ci-dessous:
if (Your Device is iPAd) //For iPad
{
[yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]];
}
else //For Other Devices then iPad
{
[yourLabel setFont:[UIFont fontWithName:@"FontName" size:FontSize]];
}
Cela fonctionne parfaitement sur tous les appareils.
aucun de ceux-ci n'a fonctionné pour moi, mais cela a fonctionné. Vous devez également utiliser la police système dans IB
#import <UIKit/UIKit.h>
@interface UILabelEx : UILabel
@end
#import "UILabelEx.h"
#import "Constants.h"
@implementation UILabelEx
- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
[super traitCollectionDidChange: previousTraitCollection];
self.font = [UIFont fontWithName:APP_FONT size:self.font.pointSize];
}
@end
toujours pas de réponse droite signée. Ce code fonctionne très bien pour moi. Vous devez désactiver la taille de police pour les classes de taille dans interface builder en premier. En IB, vous pouvez utiliser une police personnalisée.
- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
[super traitCollectionDidChange: previousTraitCollection];
if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass)
|| self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass) {
self.textField.font = [UIFont fontWithName:textField.font.fontName size:17.f];
}
}
une combinaison de quelques-unes des réponses ultérieures ci-dessus ont été utiles. Voici comment j'ai résolu Le bogue IB via une extension UILabel Swift:
import UIKit
// This extension is only required as a work-around to an interface builder bug in XCode 7.3.1
// When custom fonts are set per size class, they are reset to a small system font
// In order for this extension to work, you must set the fonts in IB to System
// We are switching any instances of ".SFUIDisplay-Bold" to "MuseoSans-700" and ".SFUIDisplay-Regular" to "MuseoSans-300" and keeping the same point size as specified in IB
extension UILabel {
override public func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
if ((traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass) || traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass) {
//let oldFontName = "\(font.fontName)-\(font.pointSize)"
if (font.fontName == systemFontRegular) {
font = UIFont(name: customFontRegular, size: (font?.pointSize)!)
//xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
}
else if (font.fontName == systemFontBold) {
font = UIFont(name: customFontBold, size: (font?.pointSize)!)
//xlog.debug("Old font: \(oldFontName) -> new Font: \(font.fontName) - \(font.pointSize)")
}
}
}
}
J'utilise Swift, XCode 6.4. C'est donc ce que j'ai fait
import Foundation
import UIKit
@IBDesignable class ExUILabel: UILabel {
@IBInspectable var fontName: String = "Default-Font" {
didSet {
self.font = UIFont(name: fontName, size:self.font.pointSize)
}
}
override func layoutSubviews() {
super.layoutSubviews()
self.font = UIFont(name: fontName, size:self.font.pointSize)
}
}
-
Goto Designer -> Identity Inspector -> Set the class to Aguilabel
-
ensuite, allez à attribut inspector dans designer et définissez le nom de la police.
j'ai trouvé un correctif encore plus rapide (je suppose que vous utilisez toujours votre police personnalisée).
créer une catégorie pour UILabel et inclure dans les fichiers en utilisant buggy storyboard avec des classes de taille et le réglage de police dédiée pour diverses classes:
@implementation UILabel (FontFixForSizeClassesAppleBug)
- (void)layoutSubviews
{
[super layoutSubviews];
if([[UIFont systemFontOfSize:10].familyName isEqualToString:self.font.familyName]) {
//workaround for interface builder size classes bug which ignores custom font if various classes defined for label: /q/custom-font-sizing-in-xcode6-size-classes-not-working-properly-with-custom-fonts-58562/"YOUR_CUSTOM_FONT_NAME" size:self.font.pointSize];
}
}
@end
utilisez simplement vos polices de caractères personnalisées dans storyboard. Lorsque buggy interpreter utilisera la police système à la place de la vôtre, cette catégorie l'activera sur votre police personnalisée.
j'ai eu le même problème et j'en ai trouvé un pas vraiment clair, mais bonne solution!
- d'abord, vous définissez la taille de police requise dans le storyboard avec le nom de police du système.
- puis à cette étiquette vous assignez une étiquette de 100 à 110 (ou plus, mais 10 était toujours suffisant pour moi dans un contrôleur de vue).
- alors mettez ce code dans le fichier source de votre CV et n'oubliez pas de changer le nom de la police. Code swift.
override func viewDidLayoutSubviews() { for i in 100...110 { if let label = view.viewWithTag(i) as? UILabel { label.font = UIFont(name: "RotondaC-Bold", size: label.font.pointSize) } } }
- ajouter les polices fournies par application dans votre application.plist
- ajouter votre .ttf fichier de l'élément 0
- l'utiliser [UIFont fontWithName:" exemple.ttf" taille:10]