Можно ли использовать динамический размер шрифта с пользовательским шрифтом в SwiftUI? - PullRequest
2 голосов
/ 23 июня 2019

Я играю с SwiftUI и хочу использовать собственный шрифт пользовательского интерфейса для моего проекта.Однако я не хочу терять динамическое изменение размера шрифта, которое поставляется со встроенными классами шрифтов (например, Large Title).

Apple предоставляет собственный модификатор шрифта для Text:

Text("Hello, world!")
    .font(.custom("Papyrus", size: 17))

Однако это фиксирует размер до 17pt.Когда вы запускаете это на устройстве или в симуляторе и открываете инспектор специальных возможностей, чтобы настроить размер шрифта на уровне ОС, элемент Text не обновляется.

Параметр size: не является обязательным, поэтомуВы должны передать что-то.И, к сожалению, вы не можете получить size существующего шрифта (даже пользовательского), потому что Font не имеет параметра size.

Кажется, что это обычный шаблон востальная часть SwiftUI, что параметры могут быть необязательными, или вы можете передать nil, чтобы явно отключить определенное поведение.Я ожидал бы, что параметр size: в .custom() будет необязательным, и внутренне либо используйте размер из предыдущего модификатора Font, либо используйте размер по умолчанию, установленный Text.

Альтернативно,статические методы, определяющие системные стили (например, .largeTitle), могут принимать аргумент, предоставляющий имя произвольного шрифта: .largeTitle("Papyrus")

Есть ли у кого-нибудь обходной путь?

Ответы [ 2 ]

2 голосов
/ 24 июня 2019

Я бы сделал это, создав собственный модификатор, который можно привязать к изменениям категории размера среды:

Всякий раз, когда вам нужно использовать Papyrus, вы должны использовать его следующим образом:

Text("Hello World!").modifier(Papyrus())

или как это:

Text("Hello World!").modifier(Papyrus(.caption))
Text("Hello World!").modifier(Papyrus(.footnote))
Text("Hello World!").modifier(Papyrus(.subheadline))
Text("Hello World!").modifier(Papyrus(.callout))
Text("Hello World!").modifier(Papyrus())
Text("Hello World!").modifier(Papyrus(.body))
Text("Hello World!").modifier(Papyrus(.headline))
Text("Hello World!").modifier(Papyrus(.title))
Text("Hello World!").modifier(Papyrus(.largeTitle))

Ваш текст теперь будет динамически меняться без дальнейшей работы.Это тот же код, реагирующий на предпочтения с разным размером текста:

enter image description here

И ваша реализация Papyrus () будет выглядеть примерно так.Вам нужно будет определить правильные значения для каждой категории, это всего лишь пример:

struct Papyrus: ViewModifier {
    @Environment(\.sizeCategory) var sizeCategory
    var textStyle: Font.TextStyle

    init(_ textStyle: Font.TextStyle = .body) {
        self.textStyle = textStyle
    }

    func body(content: Content) -> some View {
        content.font(getFont())
    }

    func getFont() -> Font {
        switch(sizeCategory) {
        case .extraSmall:
            return Font.custom("Papyrus", size: 16 * getStyleFactor())
        case .small:
            return Font.custom("Papyrus", size: 21 * getStyleFactor())
        case .medium:
            return Font.custom("Papyrus", size: 24 * getStyleFactor())
        case .large:
            return Font.custom("Papyrus", size: 28 * getStyleFactor())
        case .extraLarge:
            return Font.custom("Papyrus", size: 32 * getStyleFactor())
        case .extraExtraLarge:
            return Font.custom("Papyrus", size: 36 * getStyleFactor())
        case .extraExtraExtraLarge:
            return Font.custom("Papyrus", size: 40 * getStyleFactor())
        case .accessibilityMedium:
            return Font.custom("Papyrus", size: 48 * getStyleFactor())
        case .accessibilityLarge:
            return Font.custom("Papyrus", size: 52 * getStyleFactor())
        case .accessibilityExtraLarge:
            return Font.custom("Papyrus", size: 60 * getStyleFactor())
        case .accessibilityExtraExtraLarge:
            return Font.custom("Papyrus", size: 66 * getStyleFactor())
        case .accessibilityExtraExtraExtraLarge:
            return Font.custom("Papyrus", size: 72 * getStyleFactor())
        @unknown default:
            return Font.custom("Papyrus", size: 36 * getStyleFactor())
        }
    }

    func getStyleFactor() -> CGFloat {
        switch textStyle {
        case .caption:
            return 0.6
        case .footnote:
            return 0.7
        case .subheadline:
            return 0.8
        case .callout:
            return 0.9
        case .body:
            return 1.0
        case .headline:
            return 1.2
        case .title:
            return 1.5
        case .largeTitle:
            return 2.0
        @unknown default:
            return 1.0
        }
    }

}

ОБНОВЛЕНИЕ

Я изменил реализацию, чтобы принять текстстиль как параметр.

0 голосов
/ 06 июля 2019

Если вы хотите сохранить стиль, подобный SwiftUI, вы можете расширить Font для UIKit-совместимых платформ:

import SwiftUI

extension Font {

    #if canImport(UIKit)

    static var myHeadline = Font.custom(
        "Your-Font-Name",
        size: UIFontMetrics(forTextStyle: .headline).scaledValue(for: 17)
    )

    #endif
}

Затем, чтобы использовать его:

Text("Hello World!")
    .font(.myHeadline)

Обратите внимание, что ваши пользовательские шрифты не будут обновляться, пока вы не перезапустите приложение . Это означает, что предварительный просмотр холста также не будет работать.

Я продолжу исследовать эту тему, как только найду время для нее.

(Кроме того, это должна быть встроенная функция. Если есть Font.system(_ style: Font.TextStyle, design: Font.Design = .default), то должно быть и Font.custom(_ name: String, style: Font.TextStyle). См. FB6523689 в разделе «Обратная связь».)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...