玩转swift -- UIKit 之 UIFont

栏目: Swift · 发布时间: 8年前

内容简介:玩转swift -- UIKit 之 UIFont

一、简介

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

二、测试与详解

1、创建字体(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。

① 首先测试一下 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

测试代码如下:

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

测试结果如下图

玩转swift -- UIKit 之 UIFont

②测试一下 UIContentSizeCategoryDidChangeNotification

测试代码如下:

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

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

设置\通用\辅助功能

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

玩转swift -- UIKit 之 UIFont

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

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

如下:

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

二、创建系统字体(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;
}

结果如下:

玩转swift -- UIKit 之 UIFont

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

三、获取可用的字体名称

// 系统上可用的字体系列的名称数组
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
......(后续太多,不在列举,可以自己测试一下)

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

// 获取字体所在的字体系列的名称
open var familyName: String { get }
// 获取字体的名称
open var fontName: String { get }

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

五、获取字体指标(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 }

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

玩转swift -- UIKit 之 UIFont
字体指标示意图

六、获取字体描述符

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

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

七、完毕

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Natural Language Processing with Python

Natural Language Processing with Python

Steven Bird、Ewan Klein、Edward Loper / O'Reilly Media / 2009-7-10 / USD 44.99

This book offers a highly accessible introduction to Natural Language Processing, the field that underpins a variety of language technologies, ranging from predictive text and email filtering to autom......一起来看看 《Natural Language Processing with Python》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换