玩轉(zhuǎn)swift -- UIKit 之 UIFont

一咒吐、簡(jiǎn)介

UIFont類提供了用于獲取和設(shè)置字體信息的接口。類提供了訪問字體的特點(diǎn)属划,還提供了訪問恬叹,這是在布局過程中中使用的字體的字形信息系統(tǒng)。他們通過接受它們作為參數(shù)的方法同眯,您可以使用字體對(duì)象绽昼。下面依據(jù)源碼順序,分門別類詳細(xì)測(cè)試講解须蜗。

二硅确、測(cè)試與詳解

1、創(chuàng)建字體(Creating Fonts)

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

// 根據(jù)系統(tǒng)的用戶偏好設(shè)置及設(shè)備的SizeClass 創(chuàng)建字體
@available(iOS 10.0, *)
open class func preferredFont(forTextStyle style: UIFontTextStyle, compatibleWith traitCollection: UITraitCollection?) -> UIFont

// 根據(jù)字體的名字及字體的大小創(chuàng)建字體
public init?(name fontName: String, size fontSize: CGFloat)

// 這個(gè)方法是在現(xiàn)有字體基礎(chǔ)上獲取一個(gè)不同大小的字體
open func withSize(_ fontSize: CGFloat) -> UIFont

// 根據(jù)描述符及字體的大小去創(chuàng)建Font
@available(iOS 7.0, *)
public init(descriptor: UIFontDescriptor, size pointSize: CGFloat)

通過上面第一二個(gè)API設(shè)置之后明肮,文本控件中的字體就會(huì)以用戶的偏好設(shè)定去顯示菱农,但是如果程序在運(yùn)行的時(shí)候,用戶設(shè)置修改了字體柿估,此時(shí)再切回程序循未,字體并不會(huì)自動(dòng)的跟著變★啵基于以上的原因的妖,在iOS10以下的系統(tǒng),開發(fā)者需要監(jiān)聽 UIContentSizeCategoryDidChangeNotification 通知足陨,來重新設(shè)置字體嫂粟。在iOS10以后,需要設(shè)置文字控件的屬性 adjustsFontForContentSizeCategory為true钠右。

① 首先測(cè)試一下 UIFontTextStyle 的各種樣式赋元,樣式如下

// 標(biāo)題1樣式
@available(iOS 9.0, *)
public static let title1: UIFontTextStyle
// 標(biāo)題2樣式
@available(iOS 9.0, *)
public static let title2: UIFontTextStyle
// 標(biāo)題3樣式
@available(iOS 9.0, *)
public static let title3: UIFontTextStyle
// 大標(biāo)題樣式
@available(iOS 7.0, *)
public static let headline: UIFontTextStyle
// 小標(biāo)題樣式
@available(iOS 7.0, *)
public static let subheadline: UIFontTextStyle
// 主內(nèi)容樣式
@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

測(cè)試代碼如下:

// MARK: 測(cè)試 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;
}

測(cè)試結(jié)果如下圖

②測(cè)試一下 UIContentSizeCategoryDidChangeNotification

測(cè)試代碼如下:

// MARK: 測(cè)試 preferredFont 監(jiān)聽通知
func testPreferredFontNotify() {
        
    NotificationCenter.default.addObserver(self, selector: #selector(resetLabelStyle(notification:)), name: NSNotification.Name.UIContentSizeCategoryDidChange, object: nil)
}
    
// 回調(diào)通知
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));
        }
    };
}

接下來更改字體的大小及粗細(xì)等,路徑如下:

設(shè)置\通用\輔助功能

更改設(shè)置完畢(增加字體的字號(hào))后,切換到測(cè)試程序飒房,截圖如下:

③ 測(cè)試一下iOS10 新添加的文字控件屬性搁凸,更新系統(tǒng)字體。

在iOS10中狠毯,蘋果在UILabel中提供了一個(gè)新的屬性 adjustsFontForContentSizeCategory ,將其設(shè)置為True护糖,就可以了自動(dòng)更新了,不用監(jiān)聽那個(gè)通知了嚼松。
如下:

label.adjustsFontForContentSizeCategory = true;

經(jīng)過和與第二條的通知測(cè)試一樣的流程嫡良,結(jié)果一致锰扶。

④ 粗略講一下 UITraitCollection

為了表征 Size Classes,Apple 在 iOS 8 中引入了一個(gè)新的類寝受,UITraitCollection坷牛。這個(gè)類封裝了像水平和豎直方向的 Size Class 等信息。iOS 8 的 UIKit 中大多數(shù) UI 的基礎(chǔ)類 (包括 UIScreen很澄,UIWindow京闰,UIViewController 和 UIView) 都實(shí)現(xiàn)了 UITraitEnvironment 這個(gè)接口,通過其中的 traitCollection 這個(gè)屬性甩苛,我們可以拿到對(duì)應(yīng)的 UITraitCollection 對(duì)象蹂楣,從而得知當(dāng)前的 Size Class,并進(jìn)一步確定界面的布局讯蒲。

UIViewController 默認(rèn)遵循了UITraitEnvironment協(xié)議痊土,用來監(jiān)聽 traitCollection 的變化,如下:

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

測(cè)試一下, 在VC中添加如下代碼:

// MARK: 測(cè)試 UITraitCollection
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        
    print(previousTraitCollection ?? "測(cè)試沒有獲取到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);
        }
    };
}

運(yùn)行程序墨林,并切換橫豎屏赁酝,打印如下:

測(cè)試沒有獲取到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
>

在第一次運(yùn)行的時(shí)候,并沒有獲取到當(dāng)前的 TraitCollection ,切換后猜得到更改后的 TraitCollection 萌丈,在切回來的時(shí)候赞哗,也會(huì)打印。

但是在界面上并沒有發(fā)現(xiàn)字體有什么變化辆雾,暫時(shí)沒有想到用到第二個(gè)方法去測(cè)試肪笋,這里猜測(cè)是用來匹配自動(dòng)布局的時(shí)候,字體的縮放度迂。

⑤ 了解一下 UIFontDescriptor 字體描述符

UIFontDescriptor,即用屬性字典描述字體的機(jī)制藤乙。
可以通過字體描述符創(chuàng)建字體,也可以通過字體描述符中的屬性字典的更改來更改字體惭墓。
字體描述符并非字體坛梁,兩者是不同的概念,但是二者可進(jìn)行相互轉(zhuǎn)化腊凶。一個(gè) UIFont 對(duì)象通過其 fontDescriptor 獲得其對(duì)應(yīng)的字體描述符划咐,而UIFont通過初始化函數(shù) init(descriptor:size:) 可根據(jù)字體描述符獲取對(duì)應(yīng)的字體。
更多關(guān)于 UIFontDescriptor的初始化钧萍、屬性褐缠、方法等可參考蘋果文檔,已經(jīng)詳細(xì)表述了风瘦,之后有需要也會(huì)寫篇文章測(cè)試記錄下队魏。

二、創(chuàng)建系統(tǒng)字體(Creating System Fonts)

// 獲取指定尺寸的系統(tǒng)標(biāo)準(zhǔn)字體
open class func systemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸的系統(tǒng)粗體
open class func boldSystemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸的系統(tǒng)斜體
open class func italicSystemFont(ofSize fontSize: CGFloat) -> UIFont
// 獲取指定尺寸及粗細(xì)程度的系統(tǒng)字體
@available(iOS 8.2, *)
open class func systemFont(ofSize fontSize: CGFloat, weight: CGFloat) -> UIFont
// 獲取指定尺寸及存息程度的等寬數(shù)字系統(tǒng)字體
@available(iOS 9.0, *)
open class func monospacedDigitSystemFont(ofSize fontSize: CGFloat, weight: CGFloat) -> UIFont

不再贅述, 測(cè)試代碼如下:

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: 測(cè)試獲取系統(tǒng)字體
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;
}

結(jié)果如下:

由圖可知万搔,當(dāng)前的默認(rèn)系統(tǒng)字體與monospacedDigitSystemFont獲取到的字體是一樣的胡桨。

三官帘、獲取可用的字體名稱


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

見名知意昧谊,測(cè)試代碼如下(打印系統(tǒng)直郵的所有字體):

func getAllSystemFonts() {
        
    UIFont.familyNames.map {
            
        UIFont.fontNames(forFamilyName: $0);
            
        }.forEach { (fonts:[String]) in
                
            fonts.forEach({
                    
                print($0);
            })
    };
        
}

測(cè)試結(jié)果如下:

Copperplate-Light
Copperplate
Copperplate-Bold
KohinoorTelugu-Regular
KohinoorTelugu-Medium
KohinoorTelugu-Light
Thonburi
Thonburi-Bold
Thonburi-Light
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPSMT
......(后續(xù)太多刽虹,不在列舉,可以自己測(cè)試一下)

四揽浙、獲取字體名稱屬性(Getting Font Name Attributes)

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

這兩個(gè)屬性與第三部分一一對(duì)應(yīng)状婶,不再贅述意敛。

五馅巷、獲取字體指標(biāo)(Getting Font Metrics)

// 字體的實(shí)際大小
open var pointSize: CGFloat { get }
// 基準(zhǔn)線以上的高度
open var ascender: CGFloat { get }
// 基準(zhǔn)線以下的高度
open var descender: CGFloat { get }
// 最大文字的高度
open var capHeight: CGFloat { get }
// 小寫字母(x)的高度(相當(dāng)于最小)
open var xHeight: CGFloat { get }
// 行的高度
@available(iOS 4.0, *)
open var lineHeight: CGFloat { get }
// 字體加上下留白的高度
open var leading: CGFloat { get }

對(duì)于這部分沒有概念的話草姻,可以看一下下圖(來自維基百科):

字體指標(biāo)示意圖

六钓猬、獲取字體描述符

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

之前介紹了以下 UIFontDescriptor, 這里就不再贅述了。

七撩独、完畢

UIFont 這個(gè)類測(cè)試講解到這里就結(jié)束了敞曹,在之后的時(shí)間里,我會(huì)將swift下的UIkit的相關(guān)類依次整理一下综膀,溫故而知新澳迫!感興趣的童鞋,可以關(guān)注我的個(gè)人博客網(wǎng)站http://www.wanglongshuai.com剧劝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末橄登,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子讥此,更是在濱河造成了極大的恐慌拢锹,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萄喳,死亡現(xiàn)場(chǎng)離奇詭異卒稳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)他巨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門充坑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人染突,你說我怎么就攤上這事捻爷。” “怎么了觉痛?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵役衡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我薪棒,道長(zhǎng)手蝎,這世上最難降的妖魔是什么榕莺? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮棵介,結(jié)果婚禮上钉鸯,老公的妹妹穿的比我還像新娘。我一直安慰自己邮辽,他們只是感情好唠雕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吨述,像睡著了一般岩睁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揣云,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天捕儒,我揣著相機(jī)與錄音,去河邊找鬼邓夕。 笑死刘莹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焚刚。 我是一名探鬼主播点弯,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼矿咕!你這毒婦竟也來了抢肛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤痴腌,失蹤者是張志新(化名)和其女友劉穎雌团,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體士聪,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锦援,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剥悟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灵寺。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖区岗,靈堂內(nèi)的尸體忽然破棺而出略板,到底是詐尸還是另有隱情,我是刑警寧澤慈缔,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布叮称,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瓤檐。R本人自食惡果不足惜赂韵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望挠蛉。 院中可真熱鬧祭示,春花似錦、人聲如沸谴古。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掰担。三九已至汇陆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間恩敌,已是汗流浹背瞬测。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纠炮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓灯蝴,卻偏偏與公主長(zhǎng)得像恢口,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子穷躁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容