Đặt phông chữ mặc định cho toàn bộ ứng dụng iOS?


155

Tôi có một phông chữ tùy chỉnh tôi muốn sử dụng cho mọi thứ hiển thị văn bản trong ứng dụng, nhãn, chế độ xem văn bản, v.v.

Có cách nào để đặt phông chữ mặc định (nhãn theo mặc định sử dụng SystemFont) cho toàn bộ ứng dụng không?


7
Có ồ ạt nhìn vào tai ương này. Chúng tôi đã thành thật tìm thấy điều đơn giản nhất để làm là chỉ tạo một lớp mới (tầm thường), cho mỗi điều khiển. Vì vậy, đối với UIButton, hãy tạo SJButton. Đừng quên ghi đè cả initWithFrame và initWithCode. Đối với mỗi điều khiển (giả sử UIButton, v.v.), hãy đặt màu hoặc bất cứ thứ gì bạn thích. Hãy cẩn thận chọn kích thước (nghĩa là kích thước sẽ đặt kích thước TẮT TRÊN CÂU CHUYỆN) trong mã int, và sau đó (nếu bạn thích) sử dụng kích thước đó (và đặt, nói, phông chữ, màu sắc - bất cứ điều gì). Nó chỉ là một vài dòng mã, cực kỳ gọn gàng và giúp bạn tiết kiệm thời gian trong thời gian dài.
Fattie

@JoeBlow Cảm ơn bạn đã đăng những phát hiện của bạn - sắp dành thời gian tìm cách tự trả lời rằng
jj.

@ jj- Phải rồi. Đừng quên quá, bạn chắc chắn PHẢI sử dụng IBDesignablenhững ngày này. Hy vọng nó giúp. Cũng xem xét QA thú vị này: stackoverflow.com/a/38000466/294884
Fattie

Câu trả lời:


158

Có vẻ như có thể có trong iOS 5 bằng cách sử dụng proxy UIAppparent.

 [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:17.0]];

Điều đó sẽ đặt phông chữ thành bất cứ phông chữ tùy chỉnh nào cho tất cả các UILabels trong ứng dụng của bạn. Bạn sẽ cần lặp lại nó cho mỗi điều khiển (UIButton, UILabel, v.v.).

Hãy nhớ rằng bạn sẽ cần đặt giá trị UIAppFonts trong thông tin của mình.plist và bao gồm tên của phông chữ bạn bao gồm.


46
Cảm ơn vì sự trả lời. Tôi đã có thể làm điều này để làm việc. Bạn có biết nếu có một cách để xác định phông chữ mà không chỉ định kích thước phông chữ? Tôi có nhãn trong ứng dụng của mình không chia sẻ cùng cỡ chữ.
Brandon

23
Tôi có thể làm điều này mà không ghi đè kích thước điểm của mọi trường hợp không?
Michael Forrest

17
setFont:phương pháp không được chấp nhận
Anand

12
@Anand bạn có chắc về điều này? Tôi không thấy nó được đánh dấu là không dùng nữa UILabel. Nó không được dùng cho UIButtonnhưng nó sử dụng phông chữ cho thuộc titleLabeltính thay vì đó là một UILabel, vì vậy chỉ cần đặt phông chữ với proxy xuất hiện UILabellà ổn.
Adrian Schönig

6
@Anand nó không được dùng cho UILabel.
Alastair Stuart

118

Swift 5

Dựa trên câu trả lời của Fábio Oliveira ( https://stackoverflow.com/a/23042694/2082851 ), tôi tự thực hiện nhanh chóng 4.

Nói tóm lại, đây chức năng trao đổi phần mở rộng mặc định init(coder:), systemFont(ofSize:), boldSystemFont(ofSize:),italicSystemFont(ofSize:) với các phương pháp tùy chỉnh của tôi.

Lưu ý rằng nó không được thực hiện đầy đủ, nhưng bạn có thể trao đổi nhiều phương thức hơn dựa trên việc triển khai của tôi.

import UIKit

struct AppFontName {
    static let regular = "CourierNewPSMT"
    static let bold = "CourierNewPS-BoldMT"
    static let italic = "CourierNewPS-ItalicMT"
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {
    static var isOverrided: Bool = false

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.regular, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.bold, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: AppFontName.italic, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {
        case "CTFontRegularUsage":
            fontName = AppFontName.regular
        case "CTFontEmphasizedUsage", "CTFontBoldUsage":
            fontName = AppFontName.bold
        case "CTFontObliqueUsage":
            fontName = AppFontName.italic
        default:
            fontName = AppFontName.regular
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }

    class func overrideInitialize() {
        guard self == UIFont.self, !isOverrided else { return }

        // Avoid method swizzling run twice and revert to original initialize function
        isOverrided = true

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))), // Trick to get over the lack of UIFont.init(coder:))
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        }
    }
}


class AppDelegate: UIResponder, UIApplicationDelegate {
    // Avoid warning of Swift
    // Method 'initialize()' defines Objective-C class method 'initialize', which is not guaranteed to be invoked by Swift and will be disallowed in future versions
    override init() {
        super.init()
        UIFont.overrideInitialize()
    }
    ...
}

2
câu trả lời tốt nhất!! tự động ghi đè phông chữ hệ thống, rực rỡ
Kappe

2
Nếu ai đó có vấn đề với dòng "NSCTFontUIUsageAttribution": if let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String {đã lừa tôi.
Kiến thức

1
dường như không hoạt động với UILabels đặt kiểu văn bản (đậm, tiêu đề, tiêu đề, v.v.) ... chỉ hoạt động với phông chữ có kích thước cụ thể và bộ phông chữ hệ thống. @ nahung89
aviran

1
Điều này cũng chuyển một số phông chữ UI hệ thống. Ví dụ, danh sách gợi ý bàn phím và bảng hành động. Không biết điều này có khiến Apple từ chối ứng dụng hay không
Henry H Miao

1
Đã một năm kể từ khi câu trả lời này được đăng. Có ai có cách Apple "bản địa" hơn để đạt được điều này không?
Greg Hilston

75

Ngoài ra còn có một giải pháp khác là ghi đè lên systemFont.

Chỉ cần tạo một thể loại

UIFont + SystemFontOverride.h

#import <UIKit/UIKit.h>

@interface UIFont (SystemFontOverride)
@end

UIFont + SystemFontOverride.m

@implementation UIFont (SystemFontOverride)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

+ (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize {
    return [UIFont fontWithName:@"fontName" size:fontSize];
}

+ (UIFont *)systemFontOfSize:(CGFloat)fontSize {
    return [UIFont fontWithName:@"fontName" size:fontSize];
}

#pragma clang diagnostic pop

@end

Điều này sẽ thay thế việc triển khai mặc định và hầu hết các UIControls đều sử dụng systemFont.


1
Đây có phải là trong hướng dẫn táo?
Rambatino

Đó là một hack nhiều hơn. Tôi chưa thêm đăng ký ứng dụng của mình với bản hack này, vì nó không sử dụng bất kỳ phương thức riêng tư nào. Nếu bạn muốn một giải pháp mạnh mẽ hơn, tôi cũng khuyên bạn nên kiểm tra điều này: github.com/0xced/FontReplacer
Hugues BR

2
Điều này là tốt Apple chỉ không muốn bạn sử dụng các chức năng không có giấy tờ. Bạn được phép sử dụng các phương thức của swizzle, công khai.
mxcl

4
Khi một danh mục có các phương thức có cùng chữ ký với lớp, nó sẽ mở rộng hành vi không xác định. Để thay thế các phương thức lớp, bạn nên sử dụng phương pháp swizzling (đó cũng không phải là một ý tưởng tốt).
GreatWiz

1
Như những người khác đã chỉ ra, giải pháp này, trong khi có khả năng có hiệu quả trong phần lớn thời gian, là về mặt kỹ thuật giới thiệu tiềm năng cho hành vi không xác định. Nếu bạn không muốn mạo hiểm, phương pháp phồng có thể là một lựa chọn tốt hơn. Câu trả lời ở đây cung cấp giải pháp tương tự thông qua swizzling: stackoverflow.com/questions/19542942/iêu
Nathan Hosselton

63

Nếu bạn đang sử dụng Swift, bạn có thể tạo tiện ích mở rộng UILabel:

extension UILabel {

    @objc var substituteFontName : String {
        get { return self.font.fontName }
        set { self.font = UIFont(name: newValue, size: self.font.pointSize) }
    }

}

Và sau đó, nơi bạn làm proxy xuất hiện của bạn:

UILabel.appearance().substituteFontName = applicationFont

Có mã Objective-C tương đương sử dụng UI_APPEARANCE_SELECTORtrên một thuộc tính có tênsubstituteFontName .

Thêm vào

Đối với trường hợp bạn muốn đặt riêng các phông chữ đậm và thông thường:

extension UILabel {

    @objc var substituteFontName : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") == nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }

    @objc var substituteFontNameBold : String {
        get { return self.font.fontName }
        set { 
            if self.font.fontName.range(of:"Medium") != nil { 
                self.font = UIFont(name: newValue, size: self.font.pointSize)
            }
        }
    }
}

Sau đó, cho proxy UIAppurdy của bạn:

UILabel.appearance().substituteFontName = applicationFont
UILabel.appearance().substituteFontNameBold = applicationFontBold

Lưu ý: nếu bạn thấy rằng sự thay thế in đậm không hoạt động, có thể tên phông chữ mặc định không chứa "Trung bình". Thay đổi chuỗi đó cho một trận đấu khác khi cần thiết (nhờ Mason trong các bình luận bên dưới).


Một nhược điểm của điều này mà tôi đã tìm thấy là khi tôi bắt đầu cảnh báo bằng UIAlertControll, nút có kiểu. Hủy giống như nút có kiểu .Default (ít nhất là khi sử dụng GillSans). Trong khi bình thường. Hủy sẽ là một phông chữ trọng lượng thông thường và .Default sẽ được in đậm. Có ý kiến ​​gì không?
Mason G. Zhwiti

Xin lỗi, ý tôi là các nhãn. Hủy thường sẽ được in đậm và Mặc định thường là trọng lượng thông thường.
Mason G. Zhwiti

2
@ MasonG.Zhwiti Trong trường hợp đó, tôi có thể thiết lập UILabeltiện ích mở rộng để lấy tên phông chữ bổ sung cho đậm. Sau đó, sethãy kiểm tra xem "Bold" có trong tên phông chữ không và bỏ qua tập hợp trong một trường hợp và sử dụng nó trong trường hợp khác. Tôi sẽ chỉnh sửa và thêm một ví dụ.
Sandy Chapman

@SandyChapman Cảm ơn! Tôi đang thử kỹ thuật mới này và nó có ý nghĩa, nhưng dường như nó không hiệu quả với tôi. Tôi đang sử dụng trình giả lập GillSans và GillSans-Bold trên iOS 8.3. Bạn đã thử nghiệm kỹ thuật này?
Mason G. Zhwiti

2
@SandyChapman Tôi đã tìm ra chuyện gì đang xảy ra. Các phông chữ mặc định cho iOS 8 có xu hướng là HelveticaNeueInterface-Thường hoặc (in đậm) HelveticaNeueInterface-MediumP4. Vì vậy, tìm kiếm "Bold" không bao giờ phù hợp với bất cứ điều gì. Tôi đã thay đổi nó rangeOfString("Medium")và nó hoạt động.
Mason G. Zhwiti

23

Phát triển từ câu trả lời của Hugues BR nhưng sử dụng phương pháp làm mờ tôi đã đi đến một giải pháp thay đổi thành công tất cả các phông chữ thành một phông chữ mong muốn trong ứng dụng của tôi.

Cách tiếp cận với Kiểu động phải là những gì bạn nên tìm kiếm trên iOS 7. Giải pháp sau đây không sử dụng Kiểu động.


Ghi chú:

  • mã dưới đây, ở trạng thái được trình bày, không bao giờ được đệ trình cho Apple phê duyệt;
  • có một phiên bản ngắn hơn của nó đã thông qua đệ trình của Apple, đó là không có - initWithCoder: ghi đè. Tuy nhiên, điều đó sẽ không bao gồm tất cả các trường hợp;
  • đoạn mã sau có trong một lớp tôi sử dụng để đặt kiểu cho ứng dụng của mình, được bao gồm bởi lớp AppDelegate của tôi, do đó có sẵn ở mọi nơi và cho tất cả các phiên bản UIFont;
  • Tôi đang sử dụng Zapfino ở đây chỉ để làm cho những thay đổi rõ ràng hơn nhiều;
  • bất kỳ cải tiến nào bạn có thể tìm thấy mã này đều được chào đón.

Giải pháp này sử dụng hai phương pháp khác nhau để đạt được kết quả cuối cùng. Đầu tiên là ghi đè các phương thức lớp UIFont+ systemFontWithSize: và tương tự với sử dụng các lựa chọn thay thế của tôi (ở đây tôi sử dụng "Zapfino" để không nghi ngờ rằng việc thay thế đã thành công).

Phương pháp khác là ghi đè - initWithCoder:phương thức trên UIFont để thay thế mọi sự xuất hiện CTFontRegularUsagevà tương tự bằng các phương án của tôi. Phương pháp cuối cùng này là cần thiết bởi vì tôi thấy rằng UILabelcác đối tượng được mã hóa trong các tệp NIB không kiểm tra các + systemFontWithSize:phương thức để lấy phông chữ hệ thống của chúng và thay vào đó mã hóa chúng thành UICTFontDescriptorcác đối tượng. Tôi đã cố gắng ghi đè - awakeAfterUsingCoder:nhưng bằng cách nào đó, nó đã được gọi cho mọi đối tượng được mã hóa trong bảng phân cảnh của tôi và gây ra sự cố. Ghi đè - awakeFromNibsẽ không cho phép tôi đọc NSCoderđối tượng.

#import <objc/runtime.h>

NSString *const FORegularFontName = @"Zapfino";
NSString *const FOBoldFontName = @"Zapfino";
NSString *const FOItalicFontName = @"Zapfino";

#pragma mark - UIFont category
@implementation UIFont (CustomFonts)

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+ (void)replaceClassSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector {
    Method originalMethod = class_getClassMethod(self, originalSelector);
    Method modifiedMethod = class_getClassMethod(self, modifiedSelector);
    method_exchangeImplementations(originalMethod, modifiedMethod);
}

+ (void)replaceInstanceSelector:(SEL)originalSelector withSelector:(SEL)modifiedSelector {
    Method originalDecoderMethod = class_getInstanceMethod(self, originalSelector);
    Method modifiedDecoderMethod = class_getInstanceMethod(self, modifiedSelector);
    method_exchangeImplementations(originalDecoderMethod, modifiedDecoderMethod);
}

+ (UIFont *)regularFontWithSize:(CGFloat)size
{
    return [UIFont fontWithName:FORegularFontName size:size];
}

+ (UIFont *)boldFontWithSize:(CGFloat)size
{
    return [UIFont fontWithName:FOBoldFontName size:size];
}

+ (UIFont *)italicFontOfSize:(CGFloat)fontSize
{
    return [UIFont fontWithName:FOItalicFontName size:fontSize];
}

- (id)initCustomWithCoder:(NSCoder *)aDecoder {
    BOOL result = [aDecoder containsValueForKey:@"UIFontDescriptor"];

    if (result) {
        UIFontDescriptor *descriptor = [aDecoder decodeObjectForKey:@"UIFontDescriptor"];

        NSString *fontName;
        if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontRegularUsage"]) {
            fontName = FORegularFontName;
        }
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontEmphasizedUsage"]) {
            fontName = FOBoldFontName;
        }
        else if ([descriptor.fontAttributes[@"NSCTFontUIUsageAttribute"] isEqualToString:@"CTFontObliqueUsage"]) {
            fontName = FOItalicFontName;
        }
        else {
            fontName = descriptor.fontAttributes[@"NSFontNameAttribute"];
        }

        return [UIFont fontWithName:fontName size:descriptor.pointSize];
    }

    self = [self initCustomWithCoder:aDecoder];

    return self;
}

+ (void)load
{
    [self replaceClassSelector:@selector(systemFontOfSize:) withSelector:@selector(regularFontWithSize:)];
    [self replaceClassSelector:@selector(boldSystemFontOfSize:) withSelector:@selector(boldFontWithSize:)];
    [self replaceClassSelector:@selector(italicSystemFontOfSize:) withSelector:@selector(italicFontOfSize:)];

    [self replaceInstanceSelector:@selector(initWithCoder:) withSelector:@selector(initCustomWithCoder:)];
}
#pragma clang diagnostic pop

@end

Cách bạn sử dụng triển khai này trên iOS6 mà không có UIFontDescriptor
Utku Yıldırım

Tôi đã sử dụng khóa giải mã "UIFontTraits" để kiểm tra xem phông chữ được cung cấp có đậm hay in nghiêng hay không và thay thế nó bằng các biến thể của riêng tôi. Có nó từ ý chính này ở đây gist.github.com/Daij-Djan/5046612 .
Fábio Oliveira

Cảm ơn cho câu trả lời tôi đã sử dụng một giải pháp khác cho bây giờ. Tôi sẽ kiểm tra nó khi tôi cần nó một lần nữa :)
Utku Yıldırım

2
cảm ơn @ FábioOliveira, nó hoạt động như một cơ duyên! Chỉ một điều nữa là bạn cần đặt #import <objc / runtime.h> vào tiêu đề, nếu không bạn sẽ gặp lỗi bằng cách sử dụng lớp 'Phương thức' (lỗi tôi nhận được trong XCode 6)
nahung89

Vì một số lý do, trên iOS 8, phương thức ( UIAlertController) không thay đổi phông chữ.
Randomblue

13

Để hoàn thành câu trả lời của Sandy Chapman , đây là một giải pháp trong Objective-C (đặt danh mục này bất cứ nơi nào bạn muốn thay đổi UILabel Appearance):

@implementation UILabel (FontOverride)
- (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR {
    self.font = [UIFont fontWithName:name size:self.font.pointSize];
}
@end

Tệp giao diện, nên để phương thức này được khai báo công khai để sử dụng sau này từ những nơi như đại biểu ứng dụng của bạn:

@interface UILabel (FontOverride)
  - (void)setSubstituteFontName:(NSString *)name UI_APPEARANCE_SELECTOR;
@end

Sau đó, bạn có thể thay đổi Appearancebằng:

[[UILabel appearance] setSubstituteFontName:@"SourceSansPro-Light"];

1
Xin chào, ý bạn là "ở bất cứ đâu", mã đó sẽ phải được thêm vào trong mọi bộ điều khiển xem và có mỗi UILabel được sử dụng trong bộ điều khiển, nơi bạn muốn thay đổi phông chữ?
Jules

Không, bạn phải đặt mã này một lần , bất cứ nơi nào trong dự án của bạn; trong appdelegate của bạn chẳng hạn.
Damien Debin

1
@DamienDebin Tôi muốn sử dụng phông chữ đậm cho đậm nhưng điều này thay đổi đậm sang sáng. Có cách nào khác không?
Zeeshan

Trên thực tế, nó hoạt động, nhưng nó nên là "Thể loại" hay "Gia hạn"? Sự khác biệt được giải thích ở đây: stackoverflow.com/questions/7136124/ từ
Darius Miliauskas 8/12/2015

4

NHẬN XÉT VỀ SWift 3.0 VÀ CẢNH BÁO SWift

Bạn có thể xóa thông báo cảnh báo trong dòng:

let initCoderMethod = class_getInstanceMethod(self, Selector("initWithCoder:"))

Bằng cách thay thế nó bằng:

let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:)))

Cười lớn. Tôi không biết rằng Swift cho phép sử dụng cái này. Btw, tôi sẽ cập nhật nó để trả lời ở trên. Cảm ơn bạn @ucotta!
nahung89

4

Dành cho Swift 5

Tất cả các câu trả lời trên là chính xác nhưng tôi đã thực hiện theo cách khác nhau đó là theo kích thước thiết bị . Ở đây, trong lớp ATFontManager, tôi đã tạo kích thước phông chữ mặc định được xác định ở đầu lớp là defaultFontSize , đây là kích thước phông chữ của iphone plus và bạn có thể thay đổi theo yêu cầu của mình.

class ATFontManager: UIFont{
    
    class func setFont( _ iPhone7PlusFontSize: CGFloat? = nil,andFontName fontN : String = FontName.helveticaNeue) -> UIFont{
        
        let defaultFontSize : CGFloat = 16
        
        switch ATDeviceDetector().screenType {
            
        case .iPhone4:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 5)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 5)!
            
        case .iPhone5:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 3)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 3)!
            
        case .iPhone6AndIphone7, .iPhoneUnknownSmallSize:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize - 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize - 2)!
            
        case .iPhone6PAndIPhone7P, .iPhoneUnknownBigSize:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
        case .iPhoneX, .iPhoneXsMax:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? defaultFontSize)!
          
        case .iPadMini:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 2)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadPro10Inch:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 4)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        case .iPadPro:
            if let fontSize = iPhone7PlusFontSize{
                return UIFont(name: fontN, size: fontSize + 6)!
            }
            return UIFont(name: fontN, size: defaultFontSize + 6)!
            
        case .iPadUnknownSmallSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 2)!
            
        case .iPadUnknownBigSize:
            
            return UIFont(name: fontN, size: defaultFontSize + 4)!
            
        default:
            
            return UIFont(name: fontN, size: iPhone7PlusFontSize ?? 16)!
        }
    }
}
     

Tôi đã thêm một số tên phông chữ nhất định, để biết thêm bạn có thể thêm tên phông chữ và gõ vào đây.

   enum FontName : String {
        case HelveticaNeue = "HelveticaNeue"
        case HelveticaNeueUltraLight = "HelveticaNeue-UltraLight"
        case HelveticaNeueBold = "HelveticaNeue-Bold"
        case HelveticaNeueBoldItalic = "HelveticaNeue-BoldItalic"
        case HelveticaNeueMedium = "HelveticaNeue-Medium"
        case AvenirBlack = "Avenir-Black"
        case ArialBoldMT = "Arial-BoldMT"
        case HoeflerTextBlack = "HoeflerText-Black"
        case AMCAPEternal = "AMCAPEternal"
    }

Lớp này đề cập đến trình phát hiện thiết bị để cung cấp kích thước phông chữ phù hợp theo thiết bị.

class ATDeviceDetector {
    
    var iPhone: Bool {
        
        return UIDevice().userInterfaceIdiom == .phone
    }
    
    var ipad : Bool{
        
        return UIDevice().userInterfaceIdiom == .pad
    }
    
    let isRetina = UIScreen.main.scale >= 2.0
    
    
    enum ScreenType: String {
        
        case iPhone4
        case iPhone5
        case iPhone6AndIphone7
        case iPhone6PAndIPhone7P
        case iPhoneX
        
        case iPadMini
        case iPadPro
        case iPadPro10Inch
        
        case iPhoneOrIPadSmallSizeUnknown
        case iPadUnknown
        case unknown
    }
    
    
    struct ScreenSize{
        
        static let SCREEN_WIDTH         = UIScreen.main.bounds.size.width
        static let SCREEN_HEIGHT        = UIScreen.main.bounds.size.height
        static let SCREEN_MAX_LENGTH    = max(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
        static let SCREEN_MIN_LENGTH    = min(ScreenSize.SCREEN_WIDTH,ScreenSize.SCREEN_HEIGHT)
    }
    
    
    var screenType: ScreenType {
        
        switch ScreenSize.SCREEN_MAX_LENGTH {
            
        case 0..<568.0:
            return .iPhone4
        case 568.0:
            return .iPhone5
        case 667.0:
            return .iPhone6AndIphone7
        case 736.0:
            return .iPhone6PAndIPhone7P
        case 812.0:
            return .iPhoneX
        case 568.0..<812.0:
            return .iPhoneOrIPadSmallSizeUnknown
        case 1112.0:
            return .iPadPro10Inch
        case 1024.0:
            return .iPadMini
        case 1366.0:
            return .iPadPro
        case 812.0..<1366.0:
            return .iPadUnknown
        default:
            return .unknown
        }
    }
}

Cách sử dụng. Hy vọng nó sẽ giúp.

//for default 
label.font = ATFontManager.setFont()

//if you want to provide as your demand. Here **iPhone7PlusFontSize** variable is denoted as font size for *iphone 7plus and iphone 6 plus*, and it **ATFontManager** class automatically handle.
label.font = ATFontManager.setFont(iPhone7PlusFontSize: 15, andFontName: FontName.HelveticaNeue.rawValue)

3

Không có giải pháp nào trong số này hoạt động phổ biến trong suốt ứng dụng. Một điều tôi tìm thấy để giúp quản lý các phông chữ trong Xcode là mở Storyboard dưới dạng Mã nguồn (Bảng điều khiển nhấp chuột điều khiển trong Trình điều hướng tệp> "Mở dưới dạng"> "Nguồn"), sau đó thực hiện tìm và thay thế.


3

Kiểu phông chữ luôn được đặt trong mã và nib / bảng phân cảnh.

Đối với mã, giống như Hugues BR đã nói , làm điều đó trong catagory có thể giải quyết vấn đề.

Đối với nib / Storyboard, chúng ta có thể Phương thức Swizzling awakeFromNib để thay đổi loại phông chữ do thành phần UI từ nib / Storyboard luôn gọi nó trước khi hiển thị trên màn hình.

Tôi cho rằng bạn biết khía cạnh . Đây là một thư viện để lập trình AOP, dựa trên Phương pháp Swizzling. Chúng tôi tạo catagory cho UILabel, UIButton, UITextView để thực hiện nó.

Nhãn hiệu:

#import "UILabel+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UILabel (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UILabel* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

Nút bấm:

#import "UIButton+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UIButton (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UIButton* instance = [aspectInfo instance];
        UILabel* label = instance.titleLabel;
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:label.font.pointSize];
        instance.titleLabel.font = font;
    }error:nil];
}

@end

UITextField:

#import "UITextField+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextField (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UITextField* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

Xem UIText:

#import "UITextView+OverrideBaseFont.h"
#import "Aspects.h"

@implementation UITextView (OverrideBaseFont)

+ (void)load {
    [[self class]aspect_hookSelector:@selector(awakeFromNib) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo) {
        UITextView* instance = [aspectInfo instance];
        UIFont* font = [UIFont fontWithName:@"HelveticaNeue-light" size:instance.font.pointSize];
        instance.font = font;
    }error:nil];
}

@end

Đó là tất cả, bạn có thể thay đổi HelveticaNeue-light thành macro với tên phông chữ của bạn.


3

Tôi đã tạo chuyển đổi kiểu chữ của riêng mình cho Swift 4 sau khi xem xét một vài bài đăng, nó bao gồm hầu hết các trường hợp, chẳng hạn như:

1 Thêm phông chữ vào dự án cấu trúc và tệp .plist (có cùng tên):

<key>UIAppFonts</key>
<array>
    <string>Typo-Light.ttf</string>
    <string>Typo-Regular.ttf</string>
    <string>Typo-Semibold.ttf</string>
    <string>Typo-LightItalic.ttf</string>
</array>

Sau đó

struct Resources {

    struct Fonts {
        //struct is extended in Fonts
    }
}

extension Resources.Fonts {

    enum Weight: String {
        case light = "Typo-Light"
        case regular = "Typo-Regular"
        case semibold = "Typo-Semibold"
        case italic = "Typo-LightItalic"
    }
}

extension UIFontDescriptor.AttributeName {
    static let nsctFontUIUsage = UIFontDescriptor.AttributeName(rawValue: "NSCTFontUIUsageAttribute")
}

extension UIFont {

    @objc class func mySystemFont(ofSize: CGFloat, weight: UIFont.Weight) -> UIFont {
        switch weight {
        case .semibold, .bold, .heavy, .black:
            return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: ofSize)!

        case .medium, .regular:
            return UIFont(name: Resources.Fonts.Weight.regular.rawValue, size: ofSize)!

        default:
            return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: ofSize)!
        }
    }

    @objc class func mySystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.light.rawValue, size: size)!
    }

    @objc class func myBoldSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.semibold.rawValue, size: size)!
    }

    @objc class func myItalicSystemFont(ofSize size: CGFloat) -> UIFont {
        return UIFont(name: Resources.Fonts.Weight.italic.rawValue, size: size)!
    }

    @objc convenience init(myCoder aDecoder: NSCoder) {
        guard
            let fontDescriptor = aDecoder.decodeObject(forKey: "UIFontDescriptor") as? UIFontDescriptor,
            let fontAttribute = fontDescriptor.fontAttributes[.nsctFontUIUsage] as? String else {
                self.init(myCoder: aDecoder)
                return
        }
        var fontName = ""
        switch fontAttribute {
        case "CTFontRegularUsage", "CTFontMediumUsage":
            fontName = Resources.Fonts.Weight.regular.rawValue
        case "CTFontEmphasizedUsage", "CTFontBoldUsage", "CTFontSemiboldUsage","CTFontHeavyUsage", "CTFontBlackUsage":
            fontName = Resources.Fonts.Weight.semibold.rawValue
        case "CTFontObliqueUsage":
            fontName = Resources.Fonts.Weight.italic.rawValue
        default:
            fontName = Resources.Fonts.Weight.light.rawValue
        }
        self.init(name: fontName, size: fontDescriptor.pointSize)!
    }

    class func overrideDefaultTypography() {
        guard self == UIFont.self else { return }

        if let systemFontMethodWithWeight = class_getClassMethod(self, #selector(systemFont(ofSize: weight:))),
            let mySystemFontMethodWithWeight = class_getClassMethod(self, #selector(mySystemFont(ofSize: weight:))) {
            method_exchangeImplementations(systemFontMethodWithWeight, mySystemFontMethodWithWeight)
        }

        if let systemFontMethod = class_getClassMethod(self, #selector(systemFont(ofSize:))),
            let mySystemFontMethod = class_getClassMethod(self, #selector(mySystemFont(ofSize:))) {
            method_exchangeImplementations(systemFontMethod, mySystemFontMethod)
        }

        if let boldSystemFontMethod = class_getClassMethod(self, #selector(boldSystemFont(ofSize:))),
            let myBoldSystemFontMethod = class_getClassMethod(self, #selector(myBoldSystemFont(ofSize:))) {
            method_exchangeImplementations(boldSystemFontMethod, myBoldSystemFontMethod)
        }

        if let italicSystemFontMethod = class_getClassMethod(self, #selector(italicSystemFont(ofSize:))),
            let myItalicSystemFontMethod = class_getClassMethod(self, #selector(myItalicSystemFont(ofSize:))) {
            method_exchangeImplementations(italicSystemFontMethod, myItalicSystemFontMethod)
        }

        if let initCoderMethod = class_getInstanceMethod(self, #selector(UIFontDescriptor.init(coder:))),
            let myInitCoderMethod = class_getInstanceMethod(self, #selector(UIFont.init(myCoder:))) {
            method_exchangeImplementations(initCoderMethod, myInitCoderMethod)
        }
    }
}

Cuối cùng gọi phương thức đã tạo Appdelegatenhư sau:

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {

        UIFont.overrideDefaultTypography()
        return true
    }
}

@sheshnath bạn có thể cho chúng tôi biết thêm thông tin về sự cố không?
Javier Amor Penas

1
lỗi xin lỗi là từ phía tôi, phông chữ không được liệt kê trong thông
tin.plist

@midhunp Bạn có thể nói rõ hơn để nó không hiệu quả với bạn không?. Nó hoạt động tốt cho tôi với kiểu chữ in đậm.
Javier Amor Penas

2

Có thể là không, có thể bạn sẽ tự đặt phông chữ cho điều khiển của mình, nhưng bạn có thể làm cho quá trình dễ dàng hơn bằng cách tập trung vào nơi bạn lấy các loại phông chữ, ví dụ: có đại biểu ứng dụng hoặc một số lớp phổ biến khác có phương thức trả về phông chữ và bất cứ điều gì cần thiết để đặt phông chữ đều có thể gọi phương thức đó, điều đó sẽ giúp ích trong trường hợp bạn cần thay đổi phông chữ của mình, bạn sẽ thay đổi nó ở một nơi thay vì ở mọi nơi bạn đặt phông chữ ... Một cách khác có thể là tạo các lớp con của Các thành phần UI của bạn sẽ tự động đặt phông chữ, nhưng điều đó có thể là quá mức cần thiết ..


đối với hồ sơ, đây là những gì tôi đã làm, nhưng @Randall cần người đại diện và cung cấp một câu trả lời tốt. Tôi chỉ cần hỗ trợ dưới 5.0
Sam Jarman

4
Tôi không đồng ý với những gì bạn đã làm. Câu trả lời bạn chọn không hợp lệ khi câu hỏi của bạn được gắn thẻ iphone-sdk-4.0.
Paulo Casaretto

@Sam Jarman, câu trả lời của Randall dưới đây là chính xác - bạn có thể đánh dấu nó theo cách đó cho khách truy cập trong tương lai không?
Hóa đơn

1

NUI là một thay thế cho proxy UIAppparent. Nó cho phép bạn kiểm soát phông chữ (và nhiều thuộc tính khác) của một số lượng lớn các loại phần tử UI trong ứng dụng của bạn bằng cách sửa đổi một biểu định kiểu, có thể được sử dụng lại trên nhiều ứng dụng.

Sau khi thêm một NUILabellớp vào nhãn của bạn, bạn có thể dễ dàng kiểm soát phông chữ của chúng trong biểu định kiểu:

LabelFontName    String    Helvetica

Nếu bạn có các nhãn với các kích thước phông chữ khác nhau, bạn có thể kiểm soát kích thước của chúng bằng cách sử dụng các lớp Nhãn, LargeLabel và SmallLabel của NUI hoặc thậm chí nhanh chóng tạo các lớp của riêng bạn.


1

Đang sử dụng như loại lớp phông chữ này trong swift. Sử dụng lớp mở rộng phông chữ.

enum FontName: String {

  case regular      = "Roboto-Regular"

}

//MARK: - Set Font Size
enum FontSize: CGFloat {
    case size = 10

}
extension UIFont {

    //MARK: - Bold Font
  class var regularFont10: UIFont {
        return UIFont(name: FontName.regular.rawValue, size:FontSize.size.rawValue )!
    }
}

0

Đối với Xamarin.iOS bên trong FinishedLaunching()mã đặt của AppDelegate như thế này: -

UILabel.Appearance.Font= UIFont.FromName("Lato-Regular", 14);

đặt phông chữ cho toàn bộ ứng dụng và Thêm UIAppFontsphím '' trên Info.plist, đường dẫn phải là đường dẫn nơi tệp phông chữ của bạn .ttf nằm. Cho tôi biết nó nằm trong thư mục 'phông chữ' trong dự án của tôi.

<key>UIAppFonts</key>
    <array>
        <string>fonts/Lato-Regular.ttf</string>
    </array>

0

Như @Randall đã đề cập UIApperanceproxy iOS 5.0+ có thể được sử dụng để tùy chỉnh giao diện của tất cả các phiên bản của một lớp đọc thêm .

Xcodes tự động hoàn thành không hiển thị tất cả các thuộc tính có sẵn và có thể gây ra lỗi, nhưng bạn chỉ cần gõ nó ra và nó sẽ biên dịch.

UILabel.apperance().font = UIFont.systemFont(ofSize: 17, weight: .regular)

-1

Chúng tôi đã đạt được điều tương tự trong Swift -Xcode 7.2 bằng cách sử dụng Trình điều khiển khung nhìn cha mẹ và Trình điều khiển khung nhìn con (Kế thừa).

Tệp - Mới - Lớp Cacao Touch - ParentViewControll.

    import UIKit
    import Foundation

    class ParentViewController: UIViewController {

        var appUIColor:UIColor = UIColor.redColor()
        var appFont:UIFont = UIFont(name: "Copperplate", size: 20)!

        override func viewDidLoad() {
            super.viewDidLoad()
        }
        func addStatusBar()
        {
            let view = UIView(frame:
                CGRect(x: 0.0, y: 0.0, width: UIScreen.mainScreen().bounds.size.width, height: 20.0)
            )
            view.backgroundColor = appUIColor
            self.view.addSubview(view)
        }
    }    

Tạo các trình điều khiển xem con và liên kết với một StoryBoard VC, thêm một nhãn văn bản.

    import UIKit

    class FontTestController: ParentViewController {
        @IBOutlet var testLabel: UILabel!

        override func viewDidLoad() {
            super.viewDidLoad()
            testLabel.font =  appFont
            testLabel.textColor = appUIColor
        }

HOẶC Tạo một lớp UILabel tùy chỉnh (phương pháp phân lớp phụ) và liên kết các nhãn bắt buộc với nó.

import Foundation
import UIKit

class CustomFontLabel: UILabel {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        backgroundColor = ParentViewController().appUIColor
        font = ParentViewController().appFont
        textColor = UIColor.blackColor()
    }
}

Lưu ý: Phông chữ và màu được khai báo trong Parent Parent được triển khai trong CustomFontLabel. Ưu điểm là chúng ta có thể thay đổi các thuộc tính của uilabel / bất kỳ chế độ xem nào cùng nhau trong một số thay đổi đơn giản trong Parent VC.

2) 'cho' lặp UIView cho chế độ xem phụ. Nó chỉ hoạt động trên một VC cụ thể.

    override func viewWillLayoutSubviews() {
            for view in self.view.subviews  {
                if view.isKindOfClass(UITextField) {
                UITextField.appearance().font =  UIFont(name: "Copperplate", size: 20)
                }
                if view.isKindOfClass(UILabel) {
                    UILabel.appearance().font =  UIFont(name: "Copperplate", size: 20)    
                }               
            }       
        }
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.