Swift UIFont使用

原著地址:http://www.cocoachina.com/ios/20170612/19491.html

Swift -- UIKit UIFont


一、简介

UIFont类提供了用于获取和设置字体信息的接口。类提供了访问字体的特点,还提供了访问,这是在布局过程中中使用的字体的字形信息系统。他们通过接受它们作为参数的方法,您可以使用字体对象。下面依据源码顺序,分门别类详细测试讲解。

二、测试与详解

1、创建字体(Creating Fonts)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// 根据用户设定的字体大小及粗细设置字体

@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以后,需要设置文字控件的属性 adjustsFontForContentSizeCategorytrue

首先测试一下 UIFontTextStyle 的各种样式,样式如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

// 标题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

测试代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

// 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;

}

测试结果如下图

1497244867893606.png

②测试一下 UIContentSizeCategoryDidChangeNotification

测试代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// 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));

        }

    };

}

接下来更改字体的大小及粗细等,路径如下:

1

设置\通用\辅助功能

更改设置完毕(增加字体的字号)后,切换到测试程序,截图如下:

1497244953838149.png

测试一下iOS10 新添加的文字控件属性,更新系统字体。

iOS10中,苹果在UILabel中提供了一个新的属性 adjustsFontForContentSizeCategory ,将其设置为True,就可以了自动更新了,不用监听那个通知了。

如下:

1

label.adjustsFontForContentSizeCategory = true;

经过和与第二条的通知测试一样的流程,结果一致。

粗略讲一下 UITraitCollection

为了表征 Size ClassesApple iOS 8 中引入了一个新的类,UITraitCollection。这个类封装了像水平和竖直方向的 Size Class 等信息。iOS 8 UIKit 中大多数 UI 的基础类 (包括 UIScreenUIWindowUIViewController UIView) 都实现了 UITraitEnvironment 这个接口,通过其中的 traitCollection 这个属性,我们可以拿到对应的 UITraitCollection 对象,从而得知当前的 Size Class,并进一步确定界面的布局。

UIViewController 默认遵循了UITraitEnvironment协议,用来监听 traitCollection 的变化,如下:

1

2

 @available(iOS 8.0, *)

public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)

测试一下, VC中添加如下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

// 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);

        }

    };

}

运行程序,并切换横竖屏,打印如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

测试没有获取到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的初始化、属性、方法等可参考苹果文档,已经详细表述了,之后有需要也会写篇文章测试记录下。

二、创建系统字体(Creating System Fonts

1

2

3

4

5

6

7

8

9

10

11

12

// 获取指定尺寸的系统标准字体

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

不再赘述, 测试代码如下:

1

2

3

4

5

6

7

8

9

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));

 

}

1

2

3

4

5

6

7

8

9

10

// 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;

}

结果如下:

1497245201160223.png

由图可知,当前的默认系统字体与monospacedDigitSystemFont获取到的字体是一样的。

三、获取可用的字体名称

1

2

3

4

// 系统上可用的字体系列的名称数组

open class var familyNames: [String] { get }

// 特定字体系列中可用的字体名称数组。

open class func fontNames(forFamilyName familyName: String) -> [String]

见名知意,测试代码如下(打印系统直邮的所有字体)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

func getAllSystemFonts() {

 

    UIFont.familyNames.map {

 

        UIFont.fontNames(forFamilyName: $0);

 

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

 

            fonts.forEach({

 

                print($0);

            })

    };

}

测试结果如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

Copperplate-Light

Copperplate

Copperplate-Bold

KohinoorTelugu-Regular

KohinoorTelugu-Medium

KohinoorTelugu-Light

Thonburi

Thonburi-Bold

Thonburi-Light

CourierNewPS-BoldMT

CourierNewPS-ItalicMT

CourierNewPSMT

......(后续太多,不在列举,可以自己测试一下)

四、获取字体名称属性(Getting Font Name Attributes

1

2

3

4

// 获取字体所在的字体系列的名称

open var familyName: String { get }

// 获取字体的名称

open var fontName: String { get }

这两个属性与第三部分一一对应,不再赘述。

五、获取字体指标(Getting Font Metrics

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

// 字体的实际大小

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 }

对于这部分没有概念的话,可以看一下下图(来自维基百科):

1497245356934305.png

字体指标示意图

六、获取字体描述符

1

2

@available(iOS 7.0, *)

open var fontDescriptor: UIFontDescriptor { get }

之前介绍了以下 UIFontDescriptor, 这里就不再赘述了。

七、完毕

UIFont 这个类测试讲解到这里就结束了,在之后的时间里,我会将swift下的UIkit的相关类依次整理一下,温故而知新!感兴趣的童鞋,可以关注我的个人博客网站http://www.wanglongshuai.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值