SwiftUI์์ Font
์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ค์ ํ๋ ํ๊ธฐ์ ์ธ ๋ฐฉ๋ฒ.
import SwiftUI
import AttributedFont
let font = AttributedFont
.custom(
"Noto Sans KR",
fixedSize: 17,
attributes: .init(
kerning: -0.2,
lineHeightMultiple: 1.5
)
)
ํ์ดํฌ๊ทธ๋ํผ ์์คํ
์ ์ ์ํ ๋, ์๊ฐ๊ณผ ์ค ๋์ด๋ฅผ ํฐํธ ๊ธฐ๋ณธ๊ฐ ๋์ ์ฌ์ฉ์ ์ค์ ๊ฐ์ผ๋ก ์ง์ ์กฐ์ ํด ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ์ข
์ข
์์ต๋๋ค. ์ฐํ์ ํ์ดํฌ๊ทธ๋ํผ ์์คํ
์์๋ Spoqa Han Sans๋ฅผ ์๊ฐ๊ณผ ์ค ๋์ด๋ฅผ ์กฐ์ ํด ์ฌ์ฉํ๊ณ ์๋๋ฐ์. SwiftUI์์๋ ์๊ฐ ์กฐ์ ์ ์ํด kerning(_:)
, tracking(_:)
๋ฑ์ ๋ชจ๋ํ์ด์ด๋ฅผ ์ ๊ณตํ์ง๋ง, ์ด ๋ชจ๋ํ์ด์ด๋ค์ Text
๋ทฐ์๋ง ์ ์ฉ์ด ๊ฐ๋ฅํ๋ค๋ ํ๊ณ๊ฐ ์์ต๋๋ค. ๋ค์ ๋งํด, VStack
์ด๋ ButtonStyleConfiguration.Label
๊ฐ์ด Text
๊ฐ ์๋ ๋ทฐ์๋ ์ปค๋๊ณผ ํธ๋ํน ๊ฐ์ ์ ์ฉํ ์ ์์ต๋๋ค.
์ด ๊ฐ์ ํ๊ณ๋ @Environment
๋ฅผ ์ฌ์ฉํด ๊ฐ์ ์ ๋ฌํ๋ font(_:)
๋ชจ๋ํ์ด์ด์ ๋ค๋ฅด๊ฒ, kerning(_:)
๊ณผ tracking(_:)
๋ชจ๋ํ์ด์ด์ ๊ฒฝ์ฐ Text
์ธ์คํด์ค๋ฅผ ์ง์ ์์ ํ๋ ๋ฐฉ์์ผ๋ก ์๋ํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋๋ฐ์. ๋ฐ๋๋ก ์๊ฐํด ๋ณธ๋ค๋ฉด, ์ปค๋๊ณผ ํธ๋ํน ๊ฐ๋ @Environment
๋ฅผ ํตํด ์ ๋ฌํ ์ ์๊ฒ ๋๋ค๋ฉด ์์์ ๋ง์๋๋ ธ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฒฐ๋ก ์ ์ด๋ฅด๊ฒ ๋ฉ๋๋ค.
AttributedFont
๋ SwiftUI์ Font
๋ฅผ ํ์ฅํ์ฌ kerning
, tracking
๋ฑ์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ @Environment
๋ฅผ ํตํด ์ ๋ฌํจ์ผ๋ก์จ Text
๊ฐ ์๋ ๋ทฐ์๋ ์ปค๋๊ณผ ํธ๋ํน ๊ฐ์ ์ ์ฉํ ์ ์๋๋ก ํฉ๋๋ค. ์ฌ๊ธฐ์ ๋ํด, lineHeightMultiple
์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ง์ํจ์ผ๋ก์จ SwiftUI์ lineSpacing(_:)
๋ชจ๋ํ์ด์ด๋ก๋ ์์ ํ ๋ฌ์ฑํ ์ ์์๋ ์ค ๋์ด ๊ฐ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ๋ก ๋์์ค๋๋ค.
- ํฐํธ ์ธ์คํด์ค์ ์ปค๋๊ณผ ํธ๋ํน ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค.
- ํฐํธ ์ธ์คํด์ค์ ์ค ๋์ด ๋ฐฐ์ ๊ฐ์ ์ง์ ํ ์ ์์ต๋๋ค.
Font
์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ๊ณผ ์ ์ฌํ๊ฒ, AttributedFont
๋ custom(_:fixedSize:attributes:)
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
AttributedFont.custom("Noto Sans KR", fixedSize: 17, attributes: nil)
attributes
ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด ํฐํธ ์ธ์คํด์ค์ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ํ์ฌ AttributedFont.Attributes
๋ kerning
, tracking
, lineHeightMultiple
์ ์ธ ๊ฐ์ง ๊ฐ์ ์ง์ํฉ๋๋ค.
AttributedFont
.custom(
"Noto Sans KR",
fixedSize: 17,
attributes: .init(
kerning: -0.2,
lineHeightMultiple: 1.5
)
)
tracking
๊ณผ kerning
๊ฐ์ ๋์์ ์ง์ ํ ๊ฒฝ์ฐ, SwiftUI์์์ ๊ธฐ๋ณธ ๋์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก tracking
๊ฐ๋ง ์ ์ฉ๋๋ฉฐ kerning
๊ฐ์ ๋ฌด์๋ฉ๋๋ค.
AttributedFont
.custom(
"Noto Sans KR",
fixedSize: 17,
attributes: .init(
kerning: 0, // tracking๊ณผ ํจ๊ป ์ง์ ๋ kerning ๊ฐ์ ๋ฌด์๋ฉ๋๋ค.
tracking: -0.2,
lineHeightMultiple: 1.5
)
)
AttributedFont
๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ AttributedText
๋ฅผ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค. AttributedText
๋ AttributedFont
๋ฅผ @Environment
๋ก ๋ฐ์ ์ ์๋๋ก Text
๋ฅผ ํ์ฅ์ํจ View
์
๋๋ค.
AttributedText
๋๋ AttributedText
๋ฅผ ์๋ฒ ๋ฉํ๊ณ ์๋ ๋ทฐ์ attributedFont(_:)
๋ชจ๋ํ์ด์ด๋ฅผ ์ฌ์ฉํ์ฌ ํฐํธ ์ดํธ๋ฆฌ๋ทฐํธ๋ฅผ ์ ์ฉํฉ๋๋ค. AttributedFont
๋ AttributedText
์๋ง ์ ์ฉ๋์ด ๋ณด์ฌ์ง๋๋ค.
AttributedText("Hello, world!")
.attributedFont(
.custom(
"Noto Sans KR",
fixedSize: 17,
attributes: .init(
kerning: -0.2,
lineHeightMultiple: 1.5
)
)
)
์์ฃผ ์ฌ์ฉํ๋ ํฐํธ ์ธ์คํด์ค์ ๊ฒฝ์ฐ, AttributedFont
์ extension
์ผ๋ก ์ ์ ํ๋กํผํฐ๋ฅผ ์ ์ํ๋ฉด ๊ฐํธํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
extension AttributedFont {
static let body: Self = .custom(
"Noto Sans KR",
fixedSize: 17,
attributes: .init(
kerning: -0.2,
lineHeightMultiple: 1.5
)
)
}
AttributedText("Hello, world!")
.attributedFont(.body)
AttributedFont
์ AttributedText
๋ Font
์ Text
์์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋๋ถ๋ถ์ ๋ชจ๋ํ์ด์ด์ ์ฐ์ฐ์๋ฅผ ์ง์ํฉ๋๋ค.
AttributedFont
struct AttributedFont: Equatable, Hashable {
// Creating Custom Fonts
static func custom(_ name: String, fixedSize: CGFloat, attributes: Attributes) -> Self
// Styling a Font
func italic() -> Self
func smallCaps() -> Self
func lowercaseSmallCaps() -> Self
func uppercaseSmallCaps() -> Self
func monospacedDigit() -> Self
func weight(_ weight: Font.Weight) -> Self
func bold() -> Self
func monospaced() -> Self
func leading(_ leading: Font.Leading) -> Self
}
AttributedText
struct AttributedText: View, Equatable {
// Creating a Text View from a String
init(_ key: LocalizedStringKey, tableName: String? = nil, bundle: Bundle? = nil, comment: StaticString? = nil)
@inlinable init(verbatim content: String)
init<S: StringProtocol>(_ content: S)
// Creating a Text View from an Attributed String
init(_ attributedContent: AttributedString)
// Creating a Text View for a Date
init(_ dates: ClosedRange<Date>)
init(_ interval: DateInterval)
init(_ date: Date, style: Text.DateStyle)
// Creating a Text View with Formatting
init<F: FormatStyle>(_ input: F.FormatInput, format: F) where F.FormatInput: Equatable, F.FormatOutput == String
init<Subject: ReferenceConvertible>(_ subject: Subject, formatter: Formatter)
init<Subject: NSObject>(_ subject: Subject, formatter: Formatter)
// Creating a Text View from an Image
init(_ image: Image)
// Choosing a Font
func attributedFont(_ attributedFont: AttributedFont?) -> Self
func font(_ font: Font?) -> Self
func fontWeight(_ weight: Font.Weight?) -> Self
// Styling the Viewโs Text
func foregroundColor(_ color: Color?) -> Self
func bold() -> Self
func italic() -> Self
func monospacedDigit() -> Self
func strikethrough(_ active: Bool = true, color: Color? = nil) -> Self
func underline(_ active: Bool = true, color: Color? = nil) -> Self
func kerning(_ kerning: CGFloat) -> Self
func tracking(_ tracking: CGFloat) -> Self
func baselineOffset(_ baselineOffset: CGFloat) -> Self
// Configuring VoiceOver
func speechAlwaysIncludesPunctuation(_ value: Bool = true) -> Self
func speechSpellsOutCharacters(_ value: Bool = true) -> Self
func speechAdjustedPitch(_ value: Double) -> Self
func speechAnnouncementsQueued(_ value: Bool = true) -> Self
// Providing Accessibility Information
func accessibilityTextContentType(_ value: AccessibilityTextContentType) -> Self
func accessibilityHeading(_ level: AccessibilityHeadingLevel) -> Self
func accessibilityLabel(_ label: Text) -> Self
func accessibilityLabel(_ labelKey: LocalizedStringKey) -> Self
func accessibilityLabel<S: StringProtocol>(_ label: S) -> Self
// Combining Text Views
static func concatenate(_ views: [AttributedText], attributedFont: AttributedFont) -> Self
static func concatenate(_ views: AttributedText..., attributedFont: AttributedFont) -> Self
}
Text
์ +
์ฐ์ฐ์ ์ง์ํ๊ธฐ ์ํด, AttributedText
์์๋ concatenate(_:attributedFont:)
๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ ํ
์คํธ ๊ฒฐํฉ์ ์ง์ํฉ๋๋ค.
AttributedText.concatenate(
AttributedText("Hello,\n").attributedFont(.subheadline).foregroundColor(.secondary),
AttributedText("world!").attributedFont(.headline).foregroundColor(.primary),
attributedFont: .headline
)
lineSpacing(_:)
๊ณผ ์ํ๋จ padding(_:_:)
์ ์ฌ์ฉํ์ฌ lineHeightMultiple
์ ์ ์ฉํ๋ AttributedText
์ ํน์ฑ์ผ๋ก ์ธํด, ์ฌ๋ฌ ๊ฐ์ AttributedText
๋ฅผ ๊ฒฐํฉํ ๋์๋ ๊ฐ๋ณ์ ์ผ๋ก ์ค์ ๋ lineHeightMultiple
๊ฐ์ด ๋ฌด์๋๋ฉฐ, concatenate(_:attributedFont:)
๋ฉ์๋์ ๋ง์ง๋ง ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ attributedFont
์ lineHeightMultiple
๊ฐ์ ์ ์ฒด ์ ์ฉํฉ๋๋ค.
- Swift 5.3+
- Xcode 12.0+
- iOS 14.0+
- Mac Catalyst 14.0+
- macOS 11.0+
- tvOS 14.0+
- watchOS 7.0+
Package.swift
ํ์ผ์ dependencies
์ ์๋ ๋ผ์ธ์ ์ถ๊ฐํฉ๋๋ค.
.package(url: "https://github.com/christmas-blues/AttributedFont.git", .upToNextMajor(from: "1.0.0"))
๊ทธ ๋ค์, AttributedFont
๋ฅผ ํ๊ฒ์ ์์กด์ฑ์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
.target(name: "MyTarget", dependencies: ["AttributedFont"])
์์ฑ๋ ๋์คํฌ๋ฆฝ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
// swift-tools-version:5.1
import PackageDescription
let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://github.com/christmas-blues/AttributedFont.git", .upToNextMajor(from: "1.0.0"))
],
targets: [
.target(name: "MyTarget", dependencies: ["AttributedFont"])
]
)
File > Swift Packages > Add Package Dependency๋ฅผ ์ ํํ ๋ค์, ์๋์ URL์ ์ ๋ ฅํฉ๋๋ค.
https://github.com/christmas-blues/AttributedFont.git
์์ธํ ๋ด์ฉ์ Adding Package Dependencies to Your App์ ์ฐธ์กฐํ์ธ์.
์ ํฌ๋ ๋ชจ๋ ์ข ๋ฅ์ ๊ธฐ์ฌ๋ฅผ ํ์ํ๋ฉฐ, ๊ธฐ์ฌํด ์ฃผ์๋ ๋ถ๋ค์ ๋ชจ๋ ์๊ฒฌ์ ์กด์คํฉ๋๋ค. ๊ฐ๋จํ ๊ธฐ๋ฅ ์ถ๊ฐ, ๋ฒ๊ทธ ํฝ์ค, ์คํ ์์ ๋ฑ์ด๋ผ๋ ์ฃผ์ ํ์ง ๋ง๊ณ ์ด์๋ PR์ ์์ฑํ์ฌ ์๊ฒฌ์ ์ ๊ธฐํด ์ฃผ์ธ์.
- ๊น๋๊ท (@stleamist)
- ์ด๋ฏผํธ (@tisohjung): ์ด๊ธฐ ๋ฒ์ ์์
lineHeightMultiple
์ด ์ ๋๋ก ์ ์ฉ๋์ง ์๋ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ์์ ํด์ฃผ์ จ์ต๋๋ค.
AttributedFont
๋ MIT ๋ผ์ด์ ์ค ํ์ ๋ฐฐํฌ๋ฉ๋๋ค. ์์ธํ ๋ด์ฉ์ LICENSE๋ฅผ ์ฐธ์กฐํ์ธ์.