玩轉swift -- UIKit 之 UIFont

1、簡介

UIFont類提供了用於獲取和設置字體信息的接口。類提供了訪問字體的特色,還提供了訪問,這是在佈局過程當中中使用的字體的字形信息系統。他們經過接受它們做爲參數的方法,您可使用字體對象。下面依據源碼順序,分門別類詳細測試講解。javascript

2、測試與詳解

一、建立字體(Creating Fonts)

// 根據用戶設定的字體大小及粗細設置字體
@available(iOS 7.0, *)
open class func preferredFont(forTextStyle style: UIFontTextStyle) -> UIFont

// 根據系統的用戶偏好設置及設備的SizeClass 建立字體
@available(iOS 10.0, *)
open class func preferredFont(forTextStyle style: UIFontTextStyle, compatibleWith traitCollection: UITraitCollection?) -> UIFont

// 根據字體的名字及字體的大小建立字體
public init?(name fontName: String, size fontSize: CGFloat)

// 這個方法是在現有字體基礎上獲取一個不一樣大小的字體
open func withSize(_ fontSize: CGFloat) -> UIFont

// 根據描述符及字體的大小去建立Font
@available(iOS 7.0, *)
public init(descriptor: UIFontDescriptor, size pointSize: CGFloat)複製代碼

經過上面第一二個API設置以後,文本控件中的字體就會以用戶的偏好設定去顯示,可是若是程序在運行的時候,用戶設置修改了字體,此時再切回程序,字體並不會自動的跟着變。基於以上的緣由,在iOS10如下的系統,開發者須要監聽 UIContentSizeCategoryDidChangeNotification 通知,來從新設置字體。在iOS10之後,須要設置文字控件的屬性 adjustsFontForContentSizeCategory爲true。java

① 首先測試一下 UIFontTextStyle 的各類樣式,樣式以下

// 標題1樣式
@available(iOS 9.0, *)
public static let title1: UIFontTextStyle
// 標題2樣式
@available(iOS 9.0, *)
public static let title2: UIFontTextStyle
// 標題3樣式
@available(iOS 9.0, *)
public static let title3: UIFontTextStyle
// 大標題樣式
@available(iOS 7.0, *)
public static let headline: UIFontTextStyle
// 小標題樣式
@available(iOS 7.0, *)
public static let subheadline: UIFontTextStyle
// 主內容樣式
@available(iOS 7.0, *)
public static let body: UIFontTextStyle
// 插圖樣式
@available(iOS 9.0, *)
public static let callout: UIFontTextStyle
// 腳註樣式
@available(iOS 7.0, *)
public static let footnote: UIFontTextStyle
// 說明1樣式
@available(iOS 7.0, *)
public static let caption1: UIFontTextStyle
// 說明2樣式
@available(iOS 7.0, *)
public static let caption2: UIFontTextStyle複製代碼

測試代碼以下:ios

// MARK: 測試 preferredFont
func testFontTextStyle() {

    self.addFontLabelWithTextStyle(style: .title1);
    self.addFontLabelWithTextStyle(style: .title2);
    self.addFontLabelWithTextStyle(style: .title3);
    self.addFontLabelWithTextStyle(style: .headline);
    self.addFontLabelWithTextStyle(style: .subheadline);
    self.addFontLabelWithTextStyle(style: .body);
    self.addFontLabelWithTextStyle(style: .callout);
    self.addFontLabelWithTextStyle(style: .footnote);
    self.addFontLabelWithTextStyle(style: .caption1);
    self.addFontLabelWithTextStyle(style: .caption2);
}
// 添加label
func addFontLabelWithTextStyle(style: UIFontTextStyle) {

    let label = UILabel.init(frame: CGRect.init(x: 40, y: 80 + self.textStyleIndex * 40, width: 400, height: 20));
    label.text = String(style.rawValue);
    label.font = UIFont.preferredFont(forTextStyle: style);
    self.view.addSubview(label);

    self.textStyleIndex += 1;
}複製代碼

測試結果以下圖git

②測試一下 UIContentSizeCategoryDidChangeNotification

測試代碼以下:swift

// MARK: 測試 preferredFont 監聽通知
func testPreferredFontNotify() {

    NotificationCenter.default.addObserver(self, selector: #selector(resetLabelStyle(notification:)), name: NSNotification.Name.UIContentSizeCategoryDidChange, object: nil)
}

// 回調通知
func resetLabelStyle(notification: Notification) {

    self.view.subviews.forEach { (view) in

        if view is UILabel {

            let label = view as! UILabel;
            let style = label.font.fontDescriptor.object(forKey: UIFontDescriptorTextStyleAttribute) as! String
            label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle(rawValue: style));
        }
    };
}複製代碼

接下來更改字體的大小及粗細等,路徑以下:數組

設置\通用\輔助功能複製代碼

更改設置完畢(增長字體的字號)後,切換到測試程序,截圖以下:app

③ 測試一下iOS10 新添加的文字控件屬性,更新系統字體。

在iOS10中,蘋果在UILabel中提供了一個新的屬性 adjustsFontForContentSizeCategory ,將其設置爲True,就能夠了自動更新了,不用監聽那個通知了。
以下:ide

label.adjustsFontForContentSizeCategory = true;複製代碼

通過和與第二條的通知測試同樣的流程,結果一致。函數

④ 粗略講一下 UITraitCollection

爲了表徵 Size Classes,Apple 在 iOS 8 中引入了一個新的類,UITraitCollection。這個類封裝了像水平和豎直方向的 Size Class 等信息。iOS 8 的 UIKit 中大多數 UI 的基礎類 (包括 UIScreen,UIWindow,UIViewController 和 UIView) 都實現了 UITraitEnvironment 這個接口,經過其中的 traitCollection 這個屬性,咱們能夠拿到對應的 UITraitCollection 對象,從而得知當前的 Size Class,並進一步肯定界面的佈局。佈局

UIViewController 默認遵循了UITraitEnvironment協議,用來監聽 traitCollection 的變化,以下:

@available(iOS 8.0, *)
public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)複製代碼

測試一下, 在VC中添加以下代碼:

// MARK: 測試 UITraitCollection
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

    print(previousTraitCollection ?? "測試沒有獲取到TraitCollection");

    guard previousTraitCollection != nil else {

        return;
    }

    self.view.subviews.forEach { (view) in

        if view is UILabel {

            let label = view as! UILabel;
            let style = label.font.fontDescriptor.object(forKey: UIFontDescriptorTextStyleAttribute) as! String
            label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle(rawValue: style), compatibleWith: previousTraitCollection);
        }
    };
}複製代碼

運行程序,並切換橫豎屏,打印以下:

測試沒有獲取到TraitCollection
<
UITraitCollection: 0x6000000daa90; 
_UITraitNameUserInterfaceIdiom = Phone,
_UITraitNameDisplayScale = 2.000000, 
_UITraitNameDisplayGamut = sRGB, 
_UITraitNameHorizontalSizeClass = Compact, _UITraitNameVerticalSizeClass = Regular,
_UITraitNameTouchLevel = 0, 
_UITraitNameInteractionModel = 1,
_UITraitNameUserInterfaceStyle = 1, 
_UITraitNameLayoutDirection = 0, 
_UITraitNameForceTouchCapability = 1, _UITraitNamePreferredContentSizeCategory = UICTContentSizeCategoryL
>複製代碼

在第一次運行的時候,並無獲取到當前的 TraitCollection ,切換後猜獲得更改後的 TraitCollection ,在切回來的時候,也會打印。

可是在界面上並無發現字體有什麼變化,暫時沒有想到用到第二個方法去測試,這裏猜想是用來匹配自動佈局的時候,字體的縮放。

⑤ 瞭解一下 UIFontDescriptor 字體描述符

UIFontDescriptor,即用屬性字典描述字體的機制。
能夠經過字體描述符建立字體,也能夠經過字體描述符中的屬性字典的更改來更改字體。
字體描述符並不是字體,二者是不一樣的概念,可是兩者可進行相互轉化。一個 UIFont 對象經過其 fontDescriptor 得到其對應的字體描述符,而UIFont經過初始化函數 init(descriptor:size:) 可根據字體描述符獲取對應的字體。
更多關於 UIFontDescriptor的初始化、屬性、方法等可參考蘋果文檔,已經詳細表述了,以後有須要也會寫篇文章測試記錄下。

2、建立系統字體(Creating System Fonts)

// 獲取指定尺寸的系統標準字體
open class func systemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸的系統粗體
open class func boldSystemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸的系統斜體
open class func italicSystemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸及粗細程度的系統字體
@available(iOS 8.2, *)
open class func systemFont(ofSize fontSize: CGFloat, weight: CGFloat) -> UIFont
// 獲取指定尺寸及存息程度的等寬數字系統字體
@available(iOS 9.0, *)
open class func monospacedDigitSystemFont(ofSize fontSize: CGFloat, weight: CGFloat) -> UIFont複製代碼

再也不贅述, 測試代碼以下:

func testGetSystemFont() {

self.addFontLabelWithFont(font: UIFont.systemFont(ofSize: 18));
self.addFontLabelWithFont(font: UIFont.boldSystemFont(ofSize: 18));
self.addFontLabelWithFont(font: UIFont.italicSystemFont(ofSize: 18));
self.addFontLabelWithFont(font: UIFont.systemFont(ofSize: 18, weight: 3));
self.addFontLabelWithFont(font: UIFont.monospacedDigitSystemFont(ofSize: 18, weight: 3));

}複製代碼
// MARK: 測試獲取系統字體
func addFontLabelWithFont(font: UIFont) {

    let label = UILabel.init(frame: CGRect.init(x: 40, y: 80 + self.textStyleIndex * 40, width: 400, height: 20));
    label.text = font.fontName;
    label.font = font;
    self.view.addSubview(label);

    self.textStyleIndex += 1;
}複製代碼

結果以下:

由圖可知,當前的默認系統字體與monospacedDigitSystemFont獲取到的字體是同樣的。

3、獲取可用的字體名稱

// 系統上可用的字體系列的名稱數組
open class var familyNames: [String] { get }
// 特定字體系列中可用的字體名稱數組。
open class func fontNames(forFamilyName familyName: String) -> [String]複製代碼

見名知意,測試代碼以下(打印系統直郵的全部字體):

func getAllSystemFonts() {

    UIFont.familyNames.map {

        UIFont.fontNames(forFamilyName: $0);

        }.forEach { (fonts:[String]) in

            fonts.forEach({

                print($0);
            })
    };

}複製代碼

測試結果以下:

Copperplate-Light
Copperplate
Copperplate-Bold
KohinoorTelugu-Regular
KohinoorTelugu-Medium
KohinoorTelugu-Light
Thonburi
Thonburi-Bold
Thonburi-Light
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPSMT
......(後續太多,不在列舉,能夠本身測試一下)複製代碼

4、獲取字體名稱屬性(Getting Font Name Attributes)

// 獲取字體所在的字體系列的名稱
open var familyName: String { get }
// 獲取字體的名稱
open var fontName: String { get }複製代碼

這兩個屬性與第三部分一一對應,再也不贅述。

5、獲取字體指標(Getting Font Metrics)

// 字體的實際大小
open var pointSize: CGFloat { get }
// 基準線以上的高度
open var ascender: CGFloat { get }
// 基準線如下的高度
open var descender: CGFloat { get }
// 最大文字的高度
open var capHeight: CGFloat { get }
// 小寫字母(x)的高度(至關於最小)
open var xHeight: CGFloat { get }
// 行的高度
@available(iOS 4.0, *)
open var lineHeight: CGFloat { get }
// 字體加上下留白的高度
open var leading: CGFloat { get }複製代碼

對於這部分沒有概念的話,能夠看一下下圖(來自維基百科):

字體指標示意圖

6、獲取字體描述符

@available(iOS 7.0, *)
open var fontDescriptor: UIFontDescriptor { get }複製代碼

以前介紹瞭如下 UIFontDescriptor, 這裏就再也不贅述了。

7、完畢

UIFont 這個類測試講解到這裏就結束了,在以後的時間裏,我會將swift下的UIkit的相關類依次整理一下,溫故而知新!感興趣的童鞋,能夠關注個人我的博客網站http://www.wanglongshuai.com

相關文章
相關標籤/搜索