Skip to content

Christmas-Blues/AttributedFont

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

9 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

AttributedFont

Build

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+

์„ค์น˜

Swift Package Manager

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"])
    ]
)

Xcode

File > Swift Packages > Add Package Dependency๋ฅผ ์„ ํƒํ•œ ๋‹ค์Œ, ์•„๋ž˜์˜ URL์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

https://github.com/christmas-blues/AttributedFont.git

์ž์„ธํ•œ ๋‚ด์šฉ์€ Adding Package Dependencies to Your App์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๊ธฐ์—ฌํ•˜๊ธฐ

์ €ํฌ๋Š” ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๊ธฐ์—ฌ๋ฅผ ํ™˜์˜ํ•˜๋ฉฐ, ๊ธฐ์—ฌํ•ด ์ฃผ์‹œ๋Š” ๋ถ„๋“ค์˜ ๋ชจ๋“  ์˜๊ฒฌ์„ ์กด์ค‘ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ ์ถ”๊ฐ€, ๋ฒ„๊ทธ ํ”ฝ์Šค, ์˜คํƒ€ ์ˆ˜์ • ๋“ฑ์ด๋ผ๋„ ์ฃผ์ €ํ•˜์ง€ ๋ง๊ณ  ์ด์Šˆ๋‚˜ PR์„ ์ƒ์„ฑํ•˜์—ฌ ์˜๊ฒฌ์„ ์ œ๊ธฐํ•ด ์ฃผ์„ธ์š”.

๋ฉ”์ธํ…Œ์ด๋„ˆ

๋„์›€์„ ์ฃผ์‹  ๋ถ„๋“ค

  • ์ด๋ฏผํ˜ธ (@tisohjung): ์ดˆ๊ธฐ ๋ฒ„์ „์—์„œ lineHeightMultiple์ด ์ œ๋Œ€๋กœ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  ์ˆ˜์ •ํ•ด์ฃผ์…จ์Šต๋‹ˆ๋‹ค.

๋ผ์ด์„ ์Šค

AttributedFont๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ LICENSE๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

About

A novel way to set attributes to the Font in SwiftUI.

Topics

Resources

License

Stars

Watchers

Forks

Languages