Skip to content

Instantly share code, notes, and snippets.

@a2
Created March 16, 2022 19:40
Show Gist options
  • Save a2/83b0bd1548b3259ea9f44541748f6794 to your computer and use it in GitHub Desktop.
Save a2/83b0bd1548b3259ea9f44541748f6794 to your computer and use it in GitHub Desktop.
ScaledValue
import SwiftUI
import UIKit
@propertyWrapper
struct ScaledValue: DynamicProperty {
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
private var lastDynamicTypeSize: DynamicTypeSize!
private(set) var wrappedValue: CGFloat
var unscaledValue: CGFloat {
didSet { forceUpdate() }
}
var textStyle: Font.TextStyle {
didSet { forceUpdate() }
}
init(wrappedValue: CGFloat, textStyle: Font.TextStyle = .body) {
self.unscaledValue = wrappedValue
self.wrappedValue = .nan
self.textStyle = textStyle
self.forceUpdate()
}
init(unscaledValue: CGFloat, textStyle: Font.TextStyle = .body) {
self.unscaledValue = unscaledValue
self.wrappedValue = .nan
self.textStyle = textStyle
self.forceUpdate()
}
private func calculate() -> CGFloat {
let traitCollection = UITraitCollection(preferredContentSizeCategory: UIContentSizeCategory(dynamicTypeSize))
return UIFontMetrics(forTextStyle: UIFont.TextStyle(textStyle)).scaledValue(for: unscaledValue, compatibleWith: traitCollection)
}
mutating func update() {
guard lastDynamicTypeSize != dynamicTypeSize else { return }
forceUpdate()
}
private mutating func forceUpdate() {
lastDynamicTypeSize = dynamicTypeSize
wrappedValue = calculate()
}
}
private extension UIFont.TextStyle {
init(_ textStyle: Font.TextStyle) {
switch textStyle {
case .largeTitle:
self = .largeTitle
case .title:
self = .title1
case .title2:
self = .title2
case .title3:
self = .title3
case .headline:
self = .headline
case .subheadline:
self = .subheadline
case .body:
self = .body
case .callout:
self = .callout
case .footnote:
self = .footnote
case .caption:
self = .caption1
case .caption2:
self = .caption2
@unknown default:
self = .body
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment