Last active
June 13, 2020 13:19
-
-
Save popcornomnom/8806911e081018c893930cbda0c93e49 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FontManager.swift | |
// | |
// Created by http://www.popcornomnom.com | |
// Copyright © 2020 Marharyta Lytvynenko. All rights reserved. | |
// | |
import UIKit | |
///optional type in case if you don't want to support scaled font yet | |
private let autoScaleSettings: AutoScaleSettings? = AutoScaleSettings() | |
///optional type in case if you want turn off acessability support | |
private let acessabilitySettings: DynamicTypeSettings? = DynamicTypeSettings() | |
private class AutoScaleSettings { | |
let mostPopularScreenWidth: CGFloat = 375 | |
let maxScreenWidth: CGFloat = 460 //use to prevent huge font scaling on iPad | |
let minScaleFactor: CGFloat = 0.93 //to protect scalling of very small sizes | |
} | |
private class DynamicTypeSettings { | |
let maxPointSizeScaleFactor: CGFloat | |
init(maxPointSizeScaleFactor: CGFloat = 1.25) { | |
self.maxPointSizeScaleFactor = maxPointSizeScaleFactor | |
UILabel.appearance().adjustsFontForContentSizeCategory = true | |
UITextField.appearance().adjustsFontForContentSizeCategory = true | |
} | |
} | |
//MARK: - Font Parts | |
public extension UIFont { | |
enum Family: String, CaseIterable { | |
case system = ".SFUIText" //".SFUI" | |
case inter = "Inter" | |
//easy to change default app fonts family | |
public static let defaultFamily = Family.inter | |
} | |
enum CustomWeight: String, CaseIterable { | |
case regular = "", medium, light, heavy, bold, semibold, black | |
} | |
enum Size: CGFloat, CaseIterable { | |
case h1 = 36, h2 = 28, h3 = 20 | |
case bodyL = 17, bodyM = 15, bodyS = 13 | |
var doesSupportMinScalling: Bool { return rawValue > Size.bodyM.rawValue } //readability bounds | |
} | |
private class func stringName(_ family: Family, _ weight: CustomWeight) -> String { | |
/** | |
Define incompatible family, weight here | |
in this case set defaults compatible values | |
*/ | |
let fontWeight: String | |
switch (family, weight) { | |
case (.inter, .heavy): fontWeight = CustomWeight.bold.rawValue | |
case (.inter, .light): fontWeight = "\(weight.rawValue)BETA" | |
default: fontWeight = weight.rawValue | |
} | |
//put Family and Weight together | |
let familyName = family.rawValue | |
return fontWeight.isEmpty ? "\(familyName)" : "\(familyName)-\(fontWeight)" | |
} | |
} | |
//MARK: - Initializers | |
public extension UIFont { | |
convenience init(_ size: Size, _ weight: CustomWeight) { | |
self.init(.defaultFamily, size, weight) | |
} | |
convenience init(_ family: Family = .defaultFamily, | |
_ size: Size, _ weight: CustomWeight) { | |
var _size = size.rawValue | |
if let autoScaleSettings = autoScaleSettings { | |
var ratio = (min(UIScreen.main.bounds.width, autoScaleSettings.maxScreenWidth) | |
/ autoScaleSettings.mostPopularScreenWidth) | |
ratio = max(autoScaleSettings.minScaleFactor, ratio) | |
if ratio > 1 || (ratio < 1 && size.doesSupportMinScalling) { | |
_size = round(ratio * _size) | |
} | |
} | |
if let acessabilitySettings = acessabilitySettings { | |
let originalFont = UIFont(name: UIFont.stringName(family, weight), size: _size)! | |
let scaledFont = UIFontMetrics.default.scaledFont(for: originalFont, | |
maximumPointSize: originalFont.pointSize * | |
acessabilitySettings.maxPointSizeScaleFactor) | |
self.init(descriptor: scaledFont.fontDescriptor, size: scaledFont.pointSize) | |
} else { | |
self.init(name: UIFont.stringName(family, weight), size: _size)! | |
} | |
} | |
} | |
#if DEBUG | |
extension UIFont.Size { | |
var debugDescription: String { "\(self)" } | |
} | |
extension UIFont { | |
class func printAvailableFonts() { | |
let consoleMessage = UIFont.familyNames.map { UIFont.fontNames(forFamilyName: $0) } | |
print(consoleMessage) | |
} | |
class func printAllFonts() { | |
let families = UIFont.Family.allCases | |
let sizes = UIFont.Size.allCases | |
let weights = UIFont.CustomWeight.allCases | |
let consoleMessage = families.map { family in | |
"\(family.rawValue):" + sizes.map { size in | |
"\n\t\(size.debugDescription):\n\t\t" + weights.map { weight in | |
"\(UIFont(family, size, weight))" | |
}.joined(separator: "\n\t\t") | |
}.joined(separator: "\n") | |
}.joined(separator: "\n") | |
print(consoleMessage) | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment