Định cỡ phông chữ tùy chỉnh trong các loại kích thước Xcode 6 không hoạt động bình thường với Phông chữ tùy chỉnh


104

Xcode 6 có một tính năng mới, nơi các phông chữcỡ chữ trong UILabel, UITextFieldUIButtoncó thể được thiết lập tự động dựa trên lớp kích thước của cấu hình thiết bị hiện tại, ngay trong kịch bản này. Ví dụ: bạn có thể đặt a UILabelđể sử dụng kích thước phông chữ 12 trên cấu hình "chiều rộng bất kỳ, chiều cao nhỏ gọn" (chẳng hạn như trên iPhone ở chế độ ngang) và kích thước 18 trên cấu hình "chiều rộng thông thường, chiều cao thông thường" (chẳng hạn như trên iPad ). Thêm thông tin có sẵn ở đây:

developer.apple.com/size_class

Về lý thuyết, đây là một tính năng tuyệt vời vì nó có thể khiến việc lập trình các phông chữ khác nhau trên các tính năng của giao diện người dùng dựa trên cấu hình thiết bị là không cần thiết. Hiện tại, tôi có một số mã điều kiện đặt phông chữ dựa trên loại thiết bị, nhưng rõ ràng, điều đó có nghĩa là tôi phải đặt phông chữ theo chương trình ở mọi nơi trong ứng dụng. Vì vậy, ban đầu tôi thực sự hào hứng với tính năng này, nhưng tôi nhận thấy rằng nó có một vấn đề nghiêm trọng trong việc sử dụng thực tế đối với tôi (có lẽ là một lỗi). Lưu ý rằng tôi đang xây dựng dựa trên SDK 8 và đặt mục tiêu triển khai tối thiểu của iOS 8 , vì vậy điều này không liên quan gì đến khả năng tương thích với các phiên bản iOS cũ.

Vấn đề là ở đây: Nếu tôi đặt các kích thước phông chữ khác nhau cho các lớp kích thước khác nhau và sử dụng phông chữ "Hệ thống" do iOS cung cấp , mọi thứ hoạt động như mong đợi và kích thước phông chữ thay đổi dựa trên loại kích thước. Nếu tôi sử dụng phông chữ tùy chỉnh do ứng dụng của mình cung cấp (vâng, tôi đã thiết lập phông chữ chính xác trong gói ứng dụng của mình, vì nó hoạt động theo chương trình) và đặt phông chữ tùy chỉnh thành nhãn trong bảng phân cảnh XCode 6 , điều đó cũng hoạt động như mong đợi. Nhưng khi tôi cố gắng sử dụng các kích thước khác nhau của phông chữ tùy chỉnh cho các lớp kích thước khác nhau, trong bảng phân cảnh, nó đột nhiên không hoạt động. Sự khác biệt duy nhất về cấu hình là phông chữ tôi đã chọn (phông chữ tùy chỉnh so với phông chữ Hệ thống). Thay vào đó, tất cả các phông chữ hiển thị trênthiết bị và trình mô phỏng làm phông chữ hệ thống mặc địnhkích thước mặc định , bất kể loại kích thước (và tôi đã xác minh thông qua trình gỡ lỗi rằng nó đang thay thế phông chữ hệ thống cho phông chữ thực được chỉ định trong bảng phân cảnh). Vì vậy, về cơ bản, tính năng lớp kích thước dường như bị hỏng đối với các phông chữ tùy chỉnh. Ngoài ra, thật thú vị, các phông chữ tùy chỉnh thực sự hiển thị và điều chỉnh kích thước phù hợp trong ngăn "Xem trước" của XCode 6 cho bộ điều khiển chế độ xem: nó chỉ ngừng hoạt động khi chạy trên hệ thống iOS thực tế (điều này khiến tôi nghĩ rằng tôi đang định cấu hình nó một cách chính xác) .

Tôi đã thử nhiều phông chữ tùy chỉnh khác nhau và nó dường như không hoạt động với bất kỳ phông chữ nào trong số chúng, nhưng nó luôn hoạt động nếu tôi sử dụng "Hệ thống" thay thế.

Dù sao, có ai khác đã thấy vấn đề này trong Xcode 6 không?

Mọi ý kiến ​​về việc liệu đây có phải là lỗi trong iOS 8, Xcode hay thứ gì đó không

Tôi có làm sai không?

Cách giải quyết duy nhất mà tôi đã tìm thấy, như tôi đã nói, là tiếp tục thiết lập các phông chữ theo chương trình như tôi đã làm cho khoảng ba phiên bản iOS vì điều đó hoạt động.

Nhưng tôi rất muốn có thể sử dụng tính năng này nếu tôi có thể làm cho nó hoạt động với các phông chữ tùy chỉnh. Sử dụng phông chữ Hệ thống không được chấp nhận cho thiết kế của chúng tôi.


THÔNG TIN BỔ SUNG: Kể từ Xcode 8.0, lỗi đã được sửa.


3
Tôi có thể xác nhận đây vẫn là trường hợp trong bản phát hành cửa hàng ứng dụng xCode 6.1 (6A1052d).
jodm

3
Không phải là một giải pháp, nhưng tôi đã xoay sở để khắc phục sự cố bằng cách sử dụng Danh mục. Danh mục của tôi UILabel + Font.h (tôi cũng có một cho các nút) chứa mã sau. - (void )akenFromNib {float size = [self.font pointSize]; self.font = [UIFont fontWithName: @ "YourCustomFont" size: size]; } Vì vậy, điều này cho phép chúng tôi sử dụng các lớp kích thước với phông chữ Hệ thống để đặt giá trị điểm trong các lớp kích thước khác nhau và danh mục đảm bảo rằng phông chữ chính xác được đặt. Có lẽ bạn có thể thử cho đến khi Apple phát hành bản cập nhật?
Daniel Retief Fourie

2
Vẫn không được giải quyết trong Xcode 6.3.1. Tôi tức giận vì điều này.
Fury

7
Vẫn không hoạt động với Xcode 7 cuối cùng. Không hiểu tại sao Apple không sửa nó.
ernesto

5
vẫn không làm việc trên Xcode 7.2 iOS 9.2
Mojtaba

Câu trả lời:


41

Sửa nhanh:

1) Đặt phông chữ làm Hệ thống cho các lớp kích thước

Người kiểm tra thuộc tính nhãn

2) UILabel lớp con và ghi đè phương thức "layoutSubviews" như:

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

}

Nhân tiện, nó là một kỹ thuật rất tiện lợi cho các phông chữ mang tính biểu tượng


Mặc dù đây là một giải pháp tốt nếu phông chữ được sử dụng trong toàn ứng dụng giống nhau, nhưng sẽ kém tiện lợi hơn một chút nếu bạn cần sử dụng các phông chữ khác nhau ở những nơi khác nhau, vì khi đó bạn phải có các lớp con khác nhau, v.v. Trong trường hợp của tôi, tôi đã đã thiết lập các phông chữ có lập trình và có rất nhiều cách khác nhau để bạn có thể làm điều đó. Nhưng vấn đề của câu hỏi của tôi không phải là hỏi cách thực hiện điều này theo chương trình: mà là hỏi tại sao điều này không hoạt động bình thường khi sử dụng Storyboards (đó là một lỗi của Apple).
thiếu máu

@mnemia Tôi đồng ý. Mục đích của tôi chỉ là chỉ ra một cách xử lý lỗi đó.
dao cạo 28

1
Hoạt động tuyệt vời. Tuy nhiên, bạn không cần phải phân lớp UILabel, bạn chỉ có thể ghi đè phương thức này trong dạng xem chứa nhãn và thực hiện self.label.font = ...Bằng cách này, bạn có thể sử dụng các phông chữ khác nhau ở các vị trí khác nhau.
KPM

Hoặc bạn có thể thiết lập @IBInspectable, để lưu trữ tên phông chữ, sử dụng lại cùng một lớp nhãn tùy chỉnh và yêu cầu các phông chữ khác nhau trực tiếp trong bảng phân cảnh.
Craig Grummitt,

Có giải pháp tương tự cho UITextField không?
Chris Byatt

17

Sau khi thử mọi thứ, cuối cùng tôi đã quyết định sự kết hợp của các giải pháp trên. Sử dụng 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 cho phép bạn đặt kích thước phông chữ trong Bảng phân cảnh
  • Nó sử dụng một trình didSetquan sát, để tránh các cạm bẫy từ layoutSubviews()(vòng lặp vô hạn cho chiều cao hàng của chế độ xem bảng động) và awakeFromNib()(xem nhận xét của @ cacaoNoob)
  • Nó sử dụng các lớp kích thước thay vì thành ngữ thiết bị, với hy vọng cuối cùng sử dụng điều này với @IBDesignable
  • Rất tiếc, @IBDesignablekhông hoạt động với traitCollectiontheo bài viết ngăn xếp khác này
  • Câu lệnh chuyển đổi bộ sưu tập đặc điểm được thực hiện trên UIScreen.mainScreen()thay vì selftheo bài viết ngăn xếp này

Câu trả lời tốt nhất, Nhưng buồn bã dưới Voted..Thanks
Rohit Pradhan

9

Cách giải quyết cho UILabel: giữ nguyên kích thước phông chữ trên tất cả các Loại Kích thước, nhưng thay vào đó hãy thay đổi chiều cao nhãn của bạn cho phù hợp trong từng Loại Kích thước. Nhãn của bạn phải được bật tự động uống. Nó hoạt động tốt trong trường hợp của tôi.


1
Tôi đã có thể làm điều tương tự bằng cách thay đổi chiều rộng nhãn của mình trong từng Loại kích thước. Mẹo tốt!
dmzza

1
Tôi đã không làm cho phông chữ bị thu nhỏ bằng cách đặt chiều cao cố định nhỏ hơn cho UILabel của mình, chính xác thì bạn đã làm thế nào để nó hoạt động? adjustsFontSizeToFitWidthdường như chỉ hoạt động đối với chiều rộng (mà tôi không thể sử dụng vì văn bản của nhãn là động).
ernesto

Tôi có cùng một vấn đề với điều chỉnh để phù hợp với chiều rộng
Jules

1
Tôi đã kết thúc việc thiết lập giới hạn chiều cao của Nhãn tương ứng với chiều cao của chế độ xem siêu cao. Đó là hoạt động tốt miễn là bạn đặt "Lines" tham số của Label trong IB đến 0.
Dorian Roy

8

Lỗi này (và các lỗi khác liên quan đến Xcode - Size Classes) đã gây ra cho tôi một số nỗi buồn nghiêm trọng gần đây khi tôi phải trải qua một tệp bảng phân cảnh khổng lồ hack mọi thứ.

Đối với bất kỳ ai khác ở vị trí này, tôi muốn thêm điều gì đó vào đầu câu trả lời của @ razor28 để giảm bớt nỗi đau.

Trong tệp tiêu đề của lớp con tùy chỉnh của bạn, hãy sử dụng IBInspectablecho các thuộc tính thời gian chạy của bạn. Điều này sẽ làm cho các thuộc tính này có thể truy cập được từ "Trình kiểm tra thuộc tính", trực quan ngay trên vị trí mặc định cho cài đặt phông chữ.

Ví dụ sử dụng:

@interface MyCustomLabel : UILabel

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

@end

Điều này sẽ rất hữu ích tạo ra đầu ra này:

nhập mô tả hình ảnh ở đây

Một lợi ích bổ sung là bây giờ chúng ta không phải thêm các thuộc tính thời gian chạy theo cách thủ công cho mỗi nhãn. Đây là gần nhất mà tôi có thể nhận được hành vi dự định của XCode. Hy vọng rằng một bản sửa lỗi thích hợp sẽ xuất hiện với iOS 9 vào mùa hè này.


Tôi đã thêm theo hướng dẫn của bạn nhưng tôi không thể tìm thấy quyền truy cập "Trình kiểm tra thuộc tính" trực quan trong xib vậy làm thế nào để đạt được nó?
Darshan Kunjadiya

3

Giải pháp tương tự cho giải pháp của @ razor28 nhưng tôi nghĩ phổ biến hơn một chút. Ngoài ra, hoạt động tốt trên các phiên bản iOS cũ hơn

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


Và chắc chắn, bạn có thể thiết lập overrideFontName tài sản trong giao diện Builder cho phép để tránh phải viết mã không cần thiết
Vitaly

Điều này không hiệu quả với tôi, tôi đã liệt kê tất cả các phông chữ được cài đặt trong phương pháp trên và phông chữ của tôi đã được liệt kê và gán trong biến nhưng không làm thay đổi hiển thị phông chữ trong nhãn trên trình mô phỏng và tôi giả sử thiết bị
Jules

3

Lỗi này vẫn còn hiệu lực trong XCode 7.0 GM.

Giải pháp của Razor28 gây ra vòng lặp vô hạn trong một số trường hợp. Kinh nghiệm của tôi khi sử dụng nó cùng với SwipeView .

Thay vào đó, tôi đề nghị bạn:

1) UILabel lớp con và ghi đè setFont:

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

2) Đặt lớp tùy chỉnh của UILabels của bạn và sau đó đặt các lớp kích thước phông chữ bằng cách sử dụng Phông chữ hệ thống

nhập mô tả hình ảnh ở đây


@ Maarten1909 Bạn đang đề cập đến giải pháp thay thế hoặc cách XCode đơn giản? Nếu là người đầu tiên, bạn có thể vui lòng chỉ định phiên bản để tôi cố gắng sao chép nó?
Foti Dim

Có vẻ như tôi đã sử dụng họ phông chữ sai trong suốt thời gian qua. Nó chỉ ra rằng trong trường hợp như vậy, các phông chữ được đặt lại thành phông chữ hệ thống với kích thước 14,0 pint. Lỗi của tôi. Nhưng nó có thể hữu ích cho những người khác!
Berendschot

0

Vấn đề vẫn còn đó là bạn không thể sử dụng tính năng đặt Phông chữ cho các lớp kích thước khác nhau từ trình tạo giao diện.

Chỉ cần đặt phông chữ dựa trên thiết bị bạn muốn giống như bên dưới:

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

Điều này hoạt động hoàn hảo trên tất cả các thiết bị.


0

Không ai trong số này hiệu quả với tôi, nhưng điều này đã làm. Bạn cũng cần sử dụng phông chữ hệ thống trong 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

0

Vẫn không có câu trả lời đúng có chữ ký. Mã này hoạt động tốt đối với tôi. Trước tiên, bạn phải tắt kích thước phông chữ cho các lớp kích thước trong trình tạo giao diện. Trong IB, bạn có thể sử dụng phông chữ tùy chỉnh.

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

Sự kết hợp của một số câu trả lời sau ở trên rất hữu ích. Đây là cách tôi giải quyết lỗi IB thông qua tiện ích mở rộng Swift UILabel:

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

Tôi đang sử dụng Swift, XCode 6.4. Vì vậy, đây là những gì tôi đã làm

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 -> Đặt lớp thành ExUILabel

  2. Sau đó đi tới Trình kiểm tra thuộc tính trong trình thiết kế và đặt tên phông chữ.


-1

Tôi đã nghĩ ra cách khắc phục thậm chí còn nhanh hơn (tôi cho rằng bạn luôn sử dụng một phông chữ tùy chỉnh của mình).

Tạo một danh mục cho UILabel và đưa vào các tệp bằng cách sử dụng bảng phân cảnh lỗi với các lớp kích thước và cài đặt phông chữ chuyên dụng cho các lớp khác nhau:

@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

Chỉ cần sử dụng phông chữ tùy chỉnh của bạn trong bảng phân cảnh. Khi trình thông dịch có lỗi sẽ sử dụng phông chữ hệ thống thay vì phông chữ của riêng bạn, danh mục này sẽ chuyển nó sang phông chữ tùy chỉnh của bạn.


-1: Không nên ghi đè các phương thức trong một danh mục như thế này. Lý do: stackoverflow.com/questions/5272451/… Thay vào đó, nên swizzle (mặc dù hacky) hoặc lớp con.
JRG-Developer

-6

Tôi đã gặp vấn đề tương tự và tìm thấy một vấn đề không thực sự rõ ràng, nhưng giải pháp tốt!

  1. Đầu tiên, bạn đặt kích thước phông chữ cần thiết trong bảng phân cảnh với tên phông chữ hệ thống.
  2. Sau đó, đối với nhãn này, bạn chỉ định một thẻ từ 100 đến 110 (hoặc hơn, nhưng 10 luôn là đủ đối với tôi trong một bộ điều khiển chế độ xem).
  3. Sau đó đặt mã này vào tệp nguồn VC của bạn và đừng quên thay đổi tên phông chữ. Mã nhanh chóng.
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
Không sử dụng thẻ. Sử dụng IBOutlets. Thẻ không tốt. Xem WWDC 2015 phiên 231: “Nếu bạn đang sử dụng API UIView của View With Tag hoặc Set Tag UIView, thì tôi sẽ khuyến khích bạn loại bỏ điều đó. Để thay thế cho điều này, hãy khai báo các thuộc tính trên các lớp của bạn, và sau đó bạn sẽ có các kết nối thực sự đến những khung nhìn mà bạn cần sau này. ”
KPM

Tôi buồn rằng giải pháp này không hoàn hảo, nhưng nó hoạt động!
serg_ov

-8
  • thêm Phông chữ do ứng dụng cung cấp vào ứng dụng của bạn .plist
  • thêm tệp .ttf của bạn vào mục 0
  • sử dụng nó [UIFont fontWithName: "example.ttf" size: 10]

Đây không phải là một câu trả lời cho vấn đề này. Rõ ràng là bạn có thể sử dụng phông chữ tùy chỉnh theo lập trình, nhưng điều mà câu hỏi của tôi đề cập đến là một lỗi trong iOS 8 ngăn các phông chữ tùy chỉnh tự động thay đổi tùy thuộc vào loại kích thước.
thiếu máu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.