การเพิ่มการพิมพ์แบบกำหนดเองแบบไดนามิกในโครงการ iOS ของคุณ — Nimble

บทนำ
Dynamic Type
เป็นคุณสมบัติการเข้าถึงบน iOS และ macOS คุณลักษณะนี้ช่วยให้ผู้ใช้สามารถตั้งค่ามาตราส่วนข้อความที่ใช้กับทั้งอุปกรณ์และอัปเดตโดยอัตโนมัติ สเกลสามารถใหญ่กว่าค่าเริ่มต้นสำหรับช่วยเหลือผู้ใช้ที่มีความสามารถในการมองเห็นต่ำหรือเล็กกว่าเพื่อเติมข้อมูลให้เต็มหน้าจอพร้อมกัน

ฟอนต์เริ่มต้นของ UIKit และ SwiftUI รวมฟีเจอร์นี้ไว้ภายใน สิ่งที่นักพัฒนาต้องทำคือตั้งค่าฟอนต์บนป้ายกำกับด้วยสไตล์ฟอนต์
textLabel.font = .preferredFont(forTextStyle: .body)

การเพิ่มแบบอักษรที่กำหนดเอง
เริ่มต้นด้วยการเลือกแบบอักษรที่จะใช้ในโครงการ ขอแนะนำให้ใช้แบบอักษรที่มีน้ำหนักหลายระดับเพื่อสื่อความหมายที่แตกต่างกันในแอปพลิเคชัน
สามารถดาวน์โหลดฟอนต์ได้จากแพลตฟอร์ม ฟรีเช่นGoogle Fonts
ลากไฟล์ฟอนต์ไปยังโปรเจ็กต์ Xcode แนวทางปฏิบัติที่ดีที่สุดคือการสร้างโฟลเดอร์Font
และโฟลเดอร์ย่อยสำหรับแต่ละตระกูลแบบอักษร

เปิดเป้าหมายหลักInfo.plist
และเพิ่มคีย์UIAppFonts
เป็นอาร์เรย์ ภายในอาร์เรย์ ให้เพิ่มชื่อไฟล์และนามสกุลสำหรับแต่ละฟอนต์ที่มี

ขณะนี้ไฟล์ฟอนต์ถูกนำเข้าไปยังโปรเจ็กต์และสามารถใช้งานได้โดยการสร้างอินสแตนซ์ของ UIFont
textLabel.font = UIFont(name: "Font-Name", size: UIFont.labelFontSize)
for family in UIFont.familyNames.sorted() {
let names = UIFont.fontNames(forFamilyName: family)
print("Family: \(family) Font names: \(names)")
}
// Family: Zen Old Mincho Font names: ["ZenOldMincho-Regular", "ZenOldMincho-Bold"]
วิธีที่ง่ายที่สุดในการใช้ฟอนต์แบบกำหนดเองในโปรเจ็กต์ Swift คือการกำหนดฟอนต์โดยตรงให้กับป้ายกำกับ
textLabel.font = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)
การปรับขนาดตัวอักษรบน iOS
การตั้งค่าการเข้าถึง
เปิดแอปการตั้งค่าบนอุปกรณ์หรือโปรแกรมจำลอง นำทางไปยังAccessibility > Display & Text Size > Larger Text
. แถบเลื่อนจะเปลี่ยนขนาดตัวอักษรสำหรับระบบ

การเปลี่ยนขนาดข้อความจะไม่ทำให้แอปใด ๆ เปิดใช้งาน แต่เค้าโครงจะถูกจัดใหม่
⚙️ นี่สำหรับ iOS 15 ส่วน iOS เวอร์ชันอื่นๆ จะมีความแตกต่างกันเล็กน้อย แต่ตัวเลือกควรค้นหาได้ด้วยText Size
หรือLarger Text
การแทนที่สภาพแวดล้อม Xcode
บน Xcode หลังจากเรียกใช้แอปบนโปรแกรมจำลองสำเร็จแล้ว ให้ค้นหาไฟล์Debug Area
. ประกอบด้วยDebug Area
ปุ่มที่มีสัญลักษณ์ของการสลับ ปุ่มนี้ควรเปิดEnvironment Overrides
เมนูสำหรับเครื่องจำลอง ขนาดข้อความสามารถปรับได้ด้วยแถบเลื่อนDynamic Type
สำหรับ

Environment Overrides
จะแทนที่การตั้งค่าของโปรแกรมจำลองและจะคืนค่าการตั้งค่าล่าสุดบนเครื่องจำลองเมื่อปิด
การเปิดใช้งานแอปพลิเคชันใหม่โดยเปลี่ยนการตั้งค่าอุปกรณ์ควรแสดงข้อความใหม่ในระดับใหม่ อย่างไรก็ตาม คุณไม่สามารถเปลี่ยนขนาดฟอนต์เมื่อแอปพลิเคชันกำลังทำงาน สิ่งที่ขาดหายไปคือเครื่องมือปรับขนาด แก้ไขโค้ดสำหรับตั้งข้อความฉลากดังนี้
let customFont = UIFont(name: "ZenOldMincho-Regular", size: UIFont.labelFontSize)!
label.font = UIFontMetrics.default.scaledFont(for: customFont)
label.adjustsFontForContentSizeCategory = true
เพื่อยกระดับUIFontMetrics
ความสามารถ เราขอแนะนำตัวช่วย:
func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont?
นอกเหนือจากการเพิ่มเลเยอร์อื่นให้กับUIFontMetrics
ตัวช่วยทำหน้าที่เป็นเกตเวย์สำหรับฟังก์ชันต่างๆ ที่แอปพลิเคชันสามารถทำได้ รายการข้อกำหนดประกอบด้วย:
- แบบอักษรที่กำหนดเองทั้งหมดสามารถใช้ได้ในฟังก์ชันเดียว
- ขนาดข้อความสามารถแยกแยะได้ตามลักษณะข้อความ (เช่น เนื้อความ ชื่อเรื่อง คำอธิบายภาพ ฯลฯ)
- ขนาดตัวอักษรสามารถแทนที่ได้ด้วยการตั้งค่าในแอพ
ขั้นแรก เราสร้างโปรโตคอลสำหรับเลือกแบบอักษร: DynamicFont
.
protocol DynamicFont {
func fontName() -> String
func fontSize(style: UIFont.TextStyle) -> CGFloat
}
ตัวอย่างDynamicFont
สำหรับการสาธิตของเรามีดังนี้
enum ZenOldMincho: DynamicFont {
case regular
case bold
func fontName() -> String {
switch self {
case .regular: return "ZenOldMincho-Regular"
case .bold: return "ZenOldMincho-Bold"
}
}
func fontSize(style: UIFont.TextStyle) -> CGFloat {
switch style {
case .largeTitle: return 34.0
case .title1: return 28.0
case .title2: return 22.0
case .title3: return 20.0
case .headline: return 18.0
case .body: return 17.0
case .callout: return 16.0
case .subheadline: return 15.0
case .footnote: return 13.0
case .caption1: return 12.0
case .caption2: return 11.0
default: return 17.0
}
}
}
extension UIFont {
static func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont? {
guard let customFont = UIFont(name: font.fontName(), size: font.fontSize(style: style)) else { return nil }
let scaledFont: UIFont
let metrics = UIFontMetrics(forTextStyle: style)
return scaledFont = metrics.scaledFont(
for: customFont, compatibleWith: UITraitCollection(
preferredContentSizeCategory: overrideFontSize ?? .unspecified
)
)
}
}
textLabel.font = .customFont(ZenOldMincho.regular, forTextStyle: .body)
overridedLabel.font = .customFont(ZenOldMincho.bold, forTextStyle: .headline, overrideFontSize: .small)
สามารถใช้ Helper เวอร์ชันด้านบนได้ทันทีบน iOS 11 UILabel
ควรadjustsFontForContentSizeCategory
กำหนดtrue
ให้อัปเดตอัตโนมัติเมื่อระบบเปลี่ยนขนาดข้อความ
label.adjustsFontForContentSizeCategory = true
label.font = .customFont(ZenOldMincho.regular, forTextStyle: .body)
label.adjustsFontForContentSizeCategory = false
label.font = .customFont(ZenOldMincho.regular, forTextStyle: .body, overrideFontSize: .small)
iOS 10
UIFontMetrics.scaledFont
ใช้ได้เฉพาะบน iOS 11 ขึ้นไป สำหรับ iOS 10 คุณจะต้องกำหนดมาตราส่วนแบบอักษรด้วยตนเองสำหรับสไตล์ข้อความและหมวดหมู่ขนาดแต่ละประเภท ตลอดจนอัปเดตแบบอักษรเมื่อขนาดข้อความของระบบเปลี่ยนแปลง
ขนาดตัวอักษร
แนะนำโปรโตคอลใหม่:
protocol DynamicFontIOS10 {
func font(for style: UIFont.TextStyle, sizeCategory: UIContentSizeCategory) -> UIFont?
}
extension ZenOldMincho: DynamicFontIOS10 {
func font(for style: UIFont.TextStyle, sizeCategory: UIContentSizeCategory) -> UIFont? {
guard let style = ZenOldMincho.fontSizeTable[style],
let size = style[sizeCategory]
else { return nil }
return UIFont(name: fontName(), size: size)
}
}
extension ZenOldMincho {
static let fontSizeTable: [UIFont.TextStyle: [UIContentSizeCategory: CGFloat]] = [
.headline: [
.accessibilityExtraExtraExtraLarge: 23.0,
.accessibilityExtraExtraLarge: 23.0,
.accessibilityExtraLarge: 23.0,
.accessibilityLarge: 23.0,
.accessibilityMedium: 23.0,
.extraExtraExtraLarge: 23.0,
.extraExtraLarge: 21.0,
.extraLarge: 19.0,
.large: 17.0,
.medium: 16.0,
.small: 15.0,
.extraSmall: 14.0
],
.body: [
.accessibilityExtraExtraExtraLarge: 53.0,
.accessibilityExtraExtraLarge: 47.0,
.accessibilityExtraLarge: 40.0,
.accessibilityLarge: 33.0,
.accessibilityMedium: 28.0,
.extraExtraExtraLarge: 23.0,
.extraExtraLarge: 21.0,
.extraLarge: 19.0,
.large: 17.0,
.medium: 16.0,
.small: 15.0,
.extraSmall: 14.0
]
// Fill with all text style
}
ฟังก์ชันcustomFont
จะต้องได้รับการแก้ไขเพื่อรองรับการปรับสเกล iOS 10
static func customFont(
_ font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: UIContentSizeCategory? = nil
) -> UIFont? {
guard let customFont = UIFont(name: font.fontName(), size: font.fontSize(style: style)) else { return nil }
let scaledFont: UIFont
if #available(iOS 11.0, *) {
let metrics = UIFontMetrics(forTextStyle: style)
scaledFont = metrics.scaledFont(
for: customFont, compatibleWith: UITraitCollection(
preferredContentSizeCategory: overrideFontSize ?? .unspecified
)
)
} else {
let sizeCategory = overrideFontSize ?? UIApplication.shared.preferredContentSizeCategory
guard let fontIOS10 = font as? DynamicFontIOS10,
let customFontIOS10 = fontIOS10.font(for: style, sizeCategory: sizeCategory)
else { return customFont }
scaledFont = customFontIOS10
}
return scaledFont
}
อัปเดตขนาดตัวอักษรโดยอัตโนมัติ
ปัจจุบัน แอปพลิเคชันจะแสดงแบบอักษรที่ถูกต้องเมื่อโหลดครั้งแรกเท่านั้น เพจจะต้องตั้งค่าฟอนต์สำหรับแต่ละคอมโพเนนต์ทุกครั้งที่เปลี่ยนขนาดข้อความ ซึ่งสามารถทำได้โดยการฟังการNotificationCenter
แจ้งเตือนของUIContentSizeCategory.didChangeNotification
protocol DynamicFontController {
func setUpContentSizeNotification(disposeBag: DisposeBag)
func updateFonts(notification: Notification)
}
extension DynamicFontController where Self: UIViewController {
func setUpContentSizeNotification(disposeBag: DisposeBag) {
NotificationCenter.default.rx.notification(UIContentSizeCategory.didChangeNotification, object: nil)
.withUnretained(self)
.take(until: rx.deallocated)
.subscribe { owner, value in
owner.updateFonts(notification: value)
}
.disposed(by: disposeBag)
}
}
สำหรับใครที่ไม่ใช่RxSwift
อย่าลืมNotificationCenter.removeObserver
โทรdeinit
.
ขนาดตัวอักษรจะอัปเดตโดยอัตโนมัติเมื่อขนาดข้อความของระบบเปลี่ยนไป
SwiftUI
SwiftUI มีตัวแก้ไขมุมมองสำหรับแก้ไขแบบอักษรโดยเฉพาะ
.font(.custom(name, size: size))
Text("Hello").font(.custom("ZenOldMincho-Regular", size: 16.0))
กำลังอัปเดตขนาดตัวอักษร
เพื่อให้สามารถอัปเดตขนาดแบบอักษรได้ ตัวแก้ไขมุมมองใหม่จะถูกใช้เพื่อพิจารณาการเปลี่ยนแปลงขนาดข้อความของระบบ
หากโปรเจ็กต์เป็น SwiftUI อย่างเดียว การประกาศที่มีอยู่customFont(_ font: DynamicFont, forTextStyle style: UIFont.TextStyle, overrideFontSize: UIContentSizeCategory? = nil) -> UIFont?
ของจะถูกละเว้น
การประกาศวิธี SwiftUI ที่เทียบเท่าคือ:
extension View {
func scaledFont(
font: DynamicFont,
forTextStyle style: UIFont.TextStyle,
overrideFontSize: ContentSizeCategory? = nil
) -> some View {
return modifier(
ScaledFont(
name: font.fontName(),
size: font.fontSize(style: style),
overrideFontSize: overrideFontSize
)
)
}
}
การประกาศScaledFont
คือ:
struct ScaledFont: ViewModifier {
@Environment(\.sizeCategory) var sizeCategory
var name: String
var size: CGFloat
var overrideFontSize: ContentSizeCategory?
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size)
return content.font(.custom(name, size: scaledSize))
}
}
ด้วยตัวปรับแต่งscaledFont
เราสามารถเปลี่ยนฟอนต์ในมุมมองใดก็ได้ที่มีลายเซ็นคล้ายกัน มุมมองที่ได้จะอัปเดตขนาดฟอนต์เมื่อการตั้งค่าของระบบเปลี่ยนไป
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline)
การใช้งานปัจจุบันScaledFont: ViewModifier
ไม่รวมถึงการแทนที่ขนาดตัวอักษรภายในแอปพลิเคชัน
เพื่ออนุญาตการแทนที่UIFontMetrics.scaledValue(for:, compatibleWith:)
จะใช้ สิ่งนี้เหมือนกันในUIKit
การนำไปใช้ อย่างไรก็ตาม การแปลงจากContentSizeCategory
เป็นUIContentSizeCategory
เพื่อให้เป็นไปตามscaledValue
อินพุตของ ' ทำได้เฉพาะกับ iOS 14 ขึ้นไปเท่านั้น
แก้ไขรหัสสำหรับScaledFont.body
:
func body(content: Content) -> some View {
let scaledSize = UIFontMetrics.default.scaledValue(for: size, compatibleWith: UITraitCollection(
preferredContentSizeCategory: UIContentSizeCategory(overrideFontSize)
))
return content.font(.custom(name, size: scaledSize))
}
เมื่อใช้ตัวปรับแต่งscaledFont
เราสามารถแทนที่ขนาดข้อความได้แล้ว
Text("Hello")
.scaledFont(font: ZenOldMincho.bold, forTextStyle: .headline, overrideFontSize: .extraLarge)
Swift พัฒนาอย่างต่อเนื่องเพื่อให้ใช้งานการช่วยสำหรับการเข้าถึงได้ง่ายเพื่อปรับปรุงคุณภาพชีวิตของผู้ใช้ ฟังก์ชันตัวช่วยที่นำเสนอในบล็อกนี้สามารถรวมเข้ากับโครงการที่มีอยู่และโครงการใหม่ได้อย่างสะดวก
ไดนามิกฟอนต์จะช่วยให้ผู้ใช้ขั้นสูงสามารถดูข้อมูลได้มากขึ้นด้วยการเหลือบมอง รวมทั้งช่วยให้ผู้ใช้ที่มีปัญหาด้านการมองเห็นสามารถใช้แอปพลิเคชันได้อย่างราบรื่น ไดนามิกฟอนต์เป็นหนึ่งในคุณสมบัติการช่วยสำหรับการเข้าถึงมากมายที่นักพัฒนาสามารถนำไปใช้เพื่อปรับปรุงแอปพลิเคชันของตนได้
ซอร์สโค้ดสำหรับโครงการนี้มีอยู่ใน พื้นที่เก็บข้อมูล ของเรา
อ้างอิง
ปรับขนาดฟอนต์แบบกำหนดเองโดยอัตโนมัติด้วย Dynamic Type วิธีใช้ Dynamic Type กับฟอนต์แบบกำหนดเอง Practical Dynamic Type
เผยแพร่ครั้งแรกที่https://nimblehq.co