Xcode 6 Boyut Sınıflarında Özel Yazı Tipi Boyutlandırma, Özel Yazı Tipleriyle düzgün çalışmıyor


104

Xcode 6 yeni özelliği vardır yazı ve yazı tipi boyutları içinde UILabel, UITextFieldve UIButtonsağ Film şeridinde, mevcut cihaz yapılandırmanın boyutu sınıfına göre otomatik olarak ayarlanabilir. Örneğin, UILabel"herhangi bir genişlik, kompakt yükseklik" (yatay iPhone'larda olduğu gibi) yapılandırmalarında 12 yazı tipi boyutunu ve "normal genişlik, normal yükseklik" yapılandırmalarında ( iPad'ler gibi ) 18 boyutunu kullanacak şekilde ayarlayabilirsiniz . Daha fazla bilgiye buradan ulaşabilirsiniz:

developer.apple.com/size_class

Bu, teoride harika bir özelliktir çünkü cihaz yapılandırmasına bağlı olarak UI özelliklerinde farklı yazı tiplerini programlı olarak ayarlamayı gereksiz hale getirebilir. Şu anda, yazı tiplerini aygıt türüne göre ayarlayan bazı koşullu kodum var, ancak açıkçası, bu, yazı tiplerini uygulamanın her yerinde programlı olarak ayarlamam gerektiği anlamına geliyor. Bu yüzden başlangıçta bu özellik beni çok heyecanlandırdı, ancak benim için ciddi bir gerçek kullanım sorunu olduğunu keşfettim (belki bir hata). Ben karşı inşa ettiğimi Not SDK 8 ve minimum dağıtım hedefi koyarak iOS 8 bu iOS eski sürümleri ile uyumluluk ilgisi yoktur, bu yüzden.

Sorun şudur: Farklı boyut sınıfları için farklı yazı tipi boyutları ayarlar ve iOS tarafından sağlanan "Sistem" yazı tipini kullanırsam , her şey beklendiği gibi çalışır ve yazı tipi boyutları boyut sınıfına göre değişir. Uygulamam tarafından sağlanan özel bir yazı tipi kullanırsam (evet, programlı olarak çalıştığı için uygulama paketimde doğru şekilde kurdum) ve özel yazı tipini bir XCode 6 film şeridinde beklendiği gibi çalışan bir etikete ayarlarsam . Ancak film şeridinde farklı boyut sınıfları için farklı boyutlarda özel yazı tipi kullanmaya çalıştığımda, aniden çalışmıyor. Yapılandırmadaki tek fark, seçtiğim yazı tipidir (Sistem yazı tipine karşı özel bir yazı tipi). Bunun yerine, tüm yazı tipleriCihaz ve simülatör olarak varsayılan sistem yazı tipi de varsayılan boyutu ne olursa olsun, boyut sınıfına ait (ve bu film şeridi belirtilen gerçek bir sistem yazı ikame olduğu hata ayıklayıcı vasıtasıyla belirlenmiş). Yani temel olarak, boyut sınıfı özelliği özel yazı tipleri için bozuk görünüyor. Ayrıca, ilginç bir şekilde, özel yazı tipleri, görünüm denetleyicisi için XCode 6 "Önizleme" bölmesinde boyutu düzgün bir şekilde görüntüler ve ayarlar: yalnızca gerçek iOS sisteminde çalışırken çalışmayı durdurur (bu da beni doğru şekilde yapılandırdığımı düşündürür) .

Birden fazla farklı özel yazı tipi denedim ve bunların hiçbirinde işe yaramıyor gibi görünüyor, ancak bunun yerine "Sistem" kullanırsam her zaman işe yarıyor.

Her neyse, Xcode 6'da bu sorunu gören var mı?

Bunun iOS 8, Xcode veya başka bir şeyde bir hata olup olmadığına dair herhangi bir fikir

Yanlış mı yapıyorum

Bulduğum tek geçici çözüm, dediğim gibi, yazı tiplerini programlı olarak iOS'un yaklaşık üç sürümünde olduğu gibi ayarlamaya devam etmektir, çünkü bu işe yarıyor.

Ancak, özel yazı tipleriyle çalışmasını sağlayabilirsem bu özelliği kullanabilmeyi çok isterim. Sistem yazı tipini kullanmak tasarımımız için kabul edilemez.


EK BİLGİ: Xcode 8.0'dan itibaren, hata düzeltildi.


3
Bunun xCode 6.1 (6A1052d) uygulama mağazası sürümünde hala geçerli olduğunu doğrulayabilirim.
jodm

3
Çözüm değil, ancak Kategori kullanarak sorunu aşmayı başardım. UILabel + Font.h kategorim (düğmeler için de bir tane var) aşağıdaki kodu içeriyor. - (void) awakeFromNib {float size = [self.font pointSize]; self.font = [UIFont fontWithName: @ "KişiselFontunuz" boyut: boyut]; } Bu nedenle, bu, farklı boyut sınıflarındaki nokta değerlerini ayarlamak için boyut sınıflarını System yazı tipiyle kullanmamıza izin verir ve kategori, doğru yazı tipinin ayarlanmasını sağlar. Belki Apple bir güncelleme yayınlayana kadar buna bir şans verebilirsin?
Daniel Retief Fourie

2
Hala Xcode 6.3.1'de çözülmedi. Buna kızgınım.
Fury

7
Hala Xcode 7 final ile çalışmıyor. Apple'ın neden düzeltmediğini anlamıyorum.
ernesto

5
hala Xcode 7.2 iOS 9.2 üzerinde çalışmıyor
Mojtaba

Yanıtlar:


41

Hızlı düzeltme:

1) Yazı tiplerini boyut sınıfları için Sistem olarak ayarlayın

Etiket nitelikleri denetçisi

2) UILabel alt sınıfını seçin ve aşağıdaki gibi "layoutSubviews" yöntemini geçersiz kılın:

- (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];
    }

}

Bu arada, ikonik yazı tipleri için çok uygun bir tekniktir.


Uygulama genelinde kullanılan yazı tipi aynıysa bu iyi bir çözüm olsa da, farklı yerlerde farklı yazı tiplerini kullanmanız gerekiyorsa biraz daha az kullanışlıdır, çünkü o zaman farklı alt sınıflara sahip olmanız gerekir vb. Benim durumumda, ben zaten programlı yazı tiplerini kurdu ve bunu yapmanın birçok farklı yolu var. Ancak sorumun amacı, bunun programlı olarak nasıl yapılacağını sormak değil: Storyboard'ları kullanarak bunun neden düzgün çalışmadığını sormaktır (bu bir Apple hatasıdır).
mnemia

@mnemia Katılıyorum. Amacım, bu hatanın üstesinden gelmenin bir yolunu göstermek.
jilet28

1
Harika çalışıyor. Yine de UILabel'i alt sınıfa self.label.font = ...ayırmanıza gerek yoktur, etiketi tutan görünümde bu yöntemi geçersiz kılabilirsiniz ve bu şekilde farklı yerlerde farklı yazı tiplerini kullanabilirsiniz.
KPM

Ya da yazı tipi adını depolamak, aynı özel etiket sınıfını yeniden kullanmak ve doğrudan film şeridinde farklı yazı tipleri talep etmek için bir @IBInspectable kurabilirsiniz.
Craig Grummitt

UITextField için benzer bir çözüm var mı?
Chris Byatt

17

Her şeyi denedikten sonra, sonunda yukarıdaki çözümlerin bir kombinasyonuna karar verdim. Xcode 7.2, Swift 2'yi kullanma.

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 Storyboard'da yazı tipi boyutunu ayarlamanıza izin verir
  • didSetTuzaklardan kaçınmak için bir gözlemci kullanır layoutSubviews()(dinamik tablo görünümü satır yükseklikleri için sonsuz döngü) ve awakeFromNib()(@ cocoaNoob'un yorumuna bakın)
  • Sonunda bunu kullanma umuduyla aygıt deyimi yerine boyut sınıflarını kullanır. @IBDesignable
  • Maalesef bu diğer yığın makalesine göre @IBDesignableçalışmıyortraitCollection
  • Özellik toplama anahtarı deyimi, bu yığın makalesi başına UIScreen.mainScreen()yerine gerçekleştirilirself

En iyi cevap, Ama ne yazık ki Oy Verildi ... Teşekkürler
Rohit Pradhan

9

Geçici çözüm için UILabeltüm Boyut Sınıflarının aynı yazı tipi boyutunu tutmak, ancak bunun yerine her Boyutu Sınıf içinde buna göre etiket yüksekliğini değiştirmek. Etiketinizde otomatik daraltma etkinleştirilmiş olmalıdır. Benim durumumda güzel çalıştı.


1
Her Beden Sınıfında etiket genişliğimi değiştirerek aynı şeyi yapabildim. İyi bahşiş!
dmzza

1
UILabel'im için daha küçük bir sabit yükseklik ayarlayarak yazı tipini küçültmedim, tam olarak nasıl çalıştırdınız? adjustsFontSizeToFitWidthsadece genişlik için çalışıyor gibi görünüyor (etiketlerin metni dinamik olduğu için kullanamıyorum).
ernesto

Genişliğe uyacak şekilde ayarlamakla aynı sorunu yaşıyorum
Jules

1
Sonunda, Etiketin yükseklik sınırlamasını süpervizörün yüksekliğiyle orantılı olarak ayarladım. Bu, IB'deki Etiketin "Çizgiler" parametresini 0'a ayarladığınız sürece sorunsuz çalışır.
Dorian Roy

8

Bu (ve diğer Xcode - Boyut Sınıfları ile ilgili) hata, son zamanlarda büyük bir hikaye panosu dosyasından geçmek zorunda kaldığım için ciddi bir üzüntüye neden oldu.

Bu pozisyondaki herhangi biri için, acıyı hafifletmek için @ razor28'in cevabının üstüne bir şeyler eklemek istiyorum.

Özel alt sınıfınızın başlık dosyasında, IBInspectableçalışma zamanı öznitelikleriniz için kullanın . Bu, bu özniteliklere, yazı tipi ayarları için varsayılan konumun görsel olarak hemen yukarısındaki "Öznitelik Denetçisi" nden erişilebilir hale getirir.

Örnek kullanım:

@interface MyCustomLabel : UILabel

    @property (nonatomic) IBInspectable NSString *fontType;
    @property (nonatomic) IBInspectable CGFloat iphoneFontSize;
    @property (nonatomic) IBInspectable CGFloat ipadFontSize;

@end

Bu, bu çıktıyı çok yararlı bir şekilde üretecektir:

görüntü açıklamasını buraya girin

Ek bir avantaj, artık her etiket için çalışma zamanı özniteliklerini manuel olarak eklememiz gerekmemesidir. Bu, XCode'un amaçlanan davranışına en yakın olanı. Umarım bu yaz iOS 9 ile uygun bir düzeltme yolda.


Talimatınıza göre ekledim ancak xib'de görsel olarak "Attributes Inspector" erişimini bulamıyorum, bu yüzden nasıl elde edebilirim?
Darshan Kunjadiya 02

3

@ Razor28'e benzer bir çözüm ama biraz daha evrensel olduğunu düşünüyorum. Ayrıca, eski iOS sürümlerinde iyi çalışıyor

https://gist.github.com/softmaxsg/8a3ce30331f9f07f023e


Ve tabii ki, Interface Builder'da property overrideFontName'i ayarlayabilirsiniz, bu da gereksiz kod yazmaktan kaçınmanızı sağlar
Vitaly

Bu benim için işe yaramadı, yukarıdaki yöntemde yüklü tüm yazı tiplerini listeledim ve yazı tipim değişkende listelendi ve atandı, ancak simülatördeki etiketteki yazı tipi gösterimini değiştirmedi ve cihazı varsayıyorum
Jules

3

Hata XCode 7.0 GM'de hala geçerlidir.

Razor28'in çözümü bazı durumlarda sonsuz döngülere neden olur. Deneyimlerim, onu SwipeView ile birlikte kullanmakla oldu .

Bunun yerine size şunları öneririm:

1) Alt sınıf UILabel ve geçersiz kılma setFont:

- (void)setFont:(UIFont *)font
{
    font = [UIFont fontWithName:(@"Montserrat") size:font.pointSize];
    [super setFont:font];
}

2) UILabels'ınızın özel sınıfını ayarlayın ve ardından Sistem yazı tipi kullanarak yazı tipi boyutu sınıflarını ayarlayın

görüntü açıklamasını buraya girin


@ Maarten1909 Geçici çözümden mi yoksa basit XCode yolundan mı bahsediyorsunuz? İlki, lütfen sürümü belirtebilir misiniz, ben de onu yeniden üretmeye çalışayım?
Foti Dim

Görünüşe göre her zaman yanlış yazı tipi ailesi adını kullanıyorum. Böyle bir durumda yazı tiplerinin 14.0 pint büyüklüğünde bir sistem yazı tipine sıfırlandığı ortaya çıktı. Benim hatam. Ama başkaları için faydalı olabilir!
Berendschot

0

Sorun, arabirim oluşturucudan farklı boyut sınıfları için Yazı Tiplerini ayarlamak için özelliği kullanamamanızdır.

Sadece aşağıdaki gibi istediğiniz cihaza göre yazı tipini ayarlayın:

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]]; 
}

Bu, tüm cihazlarda mükemmel çalışır.


0

Bunların hiçbiri benim için işe yaramadı, ama bu işe yaradı. IB'deki sistem yazı tipini de kullanmanız gerekir

#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

0

Hala imzalı doğru cevap yok. Bu kod benim için iyi çalışıyor. Önce arabirim oluşturucudaki boyut sınıfları için yazı tipi boyutunu devre dışı bırakmanız gerekir. IB'de özel yazı tipi kullanabilirsiniz.

- (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];

    }
}

0

Yukarıdaki sonraki cevaplardan bazılarının bir kombinasyonu yardımcı oldu. IB hatasını bir Swift UILabel uzantısıyla nasıl çözdüm:

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)")
            }
        }
    }
}

-1

Swift, XCode 6.4 kullanıyorum. Yani yaptığım bu

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)
        }
    }
  1. Goto Designer -> Identity Inspector -> Sınıfı ExUILabel olarak ayarlayın

  2. Ardından tasarımcıda Öznitelik denetçisine gidin ve yazı tipi adını ayarlayın.


-1

Daha da hızlı bir düzeltme buldum (her zaman bir özel yazı tipinizi kullandığınızı varsayıyorum).

UILabel için bir kategori oluşturun ve çeşitli sınıflar için boyut sınıfları ve özel yazı tipi ayarı içeren buggy storyboard kullanarak dosyalara ekleyin:

@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: http://stackoverflow.com/questions/26166737/custom-font-sizing-in-xcode6-size-classes-not-working-properly-w-custom-fonts
        self.font = [UIFont fontWithName:@"YOUR_CUSTOM_FONT_NAME" size:self.font.pointSize];
    }
}

@end

Özel yazı tiplerinizi film şeridinde kullanın. Buggy yorumlayıcı sistem yazı tipini kullanacağı zaman, sizin bu kategori sizin özel yazı tipinize geçecektir.


-1: Bunun gibi bir kategorideki yöntemleri geçersiz kılmak iyi bir fikir değil. Nedeni: stackoverflow.com/questions/5272451/… Bunun yerine, (hile olsa da) veya alt sınıfta dolaşmalı.
JRG-Developer

-6

Ben de aynı sorunu yaşadım ve bir tanesini tam olarak net bulmadım, ama iyi bir çözüm buldum!

  1. Önce, film şeridinde gerekli yazı tipi boyutunu sistem yazı tipi adıyla ayarlarsınız.
  2. Sonra bu etikete 100'den 110'a kadar bir etiket atarsınız (veya daha fazla, ancak bir görünüm denetleyicisinde 10 benim için her zaman yeterliydi).
  3. Ardından bu kodu VC'nizin kaynak dosyasına koyun ve yazı tipi adını değiştirmeyi unutmayın. Hızlıca kodlayın.
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)
        }
    }
}

1
Etiketleri kullanmayın. IBOutlets kullanın. Etiketler kötü. Bkz. WWDC 2015 231 oturumu: "Etiketle Görüntüle veya Etiket UIView API'sini Ayarla API'sini ve gönderim kodunu kullanıyorsanız, bundan uzaklaşmanızı tavsiye edeceğim. Bunun yerine, sınıflarınızdaki özellikleri belirtin ve daha sonra ihtiyaç duyduğunuz bu görünümlerle gerçek bağlantılara sahip olacaksınız. "
KPM

Bu çözümün mükemmel olmadığı için üzgünüm, ama işe yarıyor!
serg_ov

-8
  • uygulama tarafından sağlanan Yazı Tiplerini uygulamanızın .plistesine ekleyin
  • .ttf dosyanızı öğe 0'a ekleyin
  • bunu kullanın [UIFont fontWithName: "example.ttf" size: 10]

Bu, bu sorunun cevabı değil. Açıkçası özel yazı tiplerini programlı olarak kullanabilirsiniz, ancak benim sorum iOS 8'deki özel yazı tiplerinin boyut sınıfına bağlı olarak otomatik olarak değişmesini önleyen bir hatayla ilgilidir.
mnemia
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.