-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit - created package & added files
- Loading branch information
0 parents
commit f68038a
Showing
15 changed files
with
461 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"object": { | ||
"pins": [ | ||
{ | ||
"package": "HalfASheet", | ||
"repositoryURL": "https://github.com/franklynw/HalfASheet.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "2f1959c5e8a74cb078b96942d46388b7e4bebcdb", | ||
"version": "1.0.0" | ||
} | ||
} | ||
] | ||
}, | ||
"version": 1 | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// swift-tools-version:5.3 | ||
// The swift-tools-version declares the minimum version of Swift required to build this package. | ||
|
||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "FontPicker", | ||
platforms: [ | ||
.iOS(.v14) | ||
], | ||
products: [ | ||
.library( | ||
name: "FontPicker", | ||
targets: ["FontPicker"]), | ||
], | ||
dependencies: [ | ||
.package(name: "HalfASheet", url: "https://github.com/franklynw/HalfASheet.git", .upToNextMajor(from: "1.0.0")) | ||
], | ||
targets: [ | ||
.target( | ||
name: "FontPicker", | ||
dependencies: ["HalfASheet"]), | ||
.testTarget( | ||
name: "FontPickerTests", | ||
dependencies: ["FontPicker"]), | ||
] | ||
) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# FontPicker | ||
|
||
A description of this package. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// | ||
// File.swift | ||
// | ||
// | ||
// Created by Franklyn Weber on 04/02/2021. | ||
// | ||
|
||
import SwiftUI | ||
|
||
|
||
extension FontPicker { | ||
|
||
/// The color to use for the background of the picker | ||
/// - Parameter backgroundColor: a UIColor | ||
public func backgroundColor(_ backgroundColor: UIColor) -> Self { | ||
var copy = self | ||
copy.backgroundColor = backgroundColor | ||
return copy | ||
} | ||
|
||
/// Normally, selecting a font will dismiss the picker. Use this to disable that functionality (eg if you have a preview which shows how the font will look in context) | ||
public var disableDismissOnSelection: Self { | ||
var copy = self | ||
copy._dismissOnSelection = false | ||
return copy | ||
} | ||
|
||
/// Use this to display only the fonts you want | ||
/// - Parameter fontNames: the names of the fonts you want to display | ||
public func fontNames(_ fontNames: [String]) -> Self { | ||
var copy = self | ||
copy.userFontNames = fontNames | ||
return copy | ||
} | ||
|
||
/// Add your own fonts to the default list of those provided by the system | ||
/// - Parameter fontNames: the names of the fonts you want to add | ||
public func additionalFontNames(_ fontNames: [String]) -> Self { | ||
var copy = self | ||
copy.additionalFontNames = fontNames | ||
return copy | ||
} | ||
|
||
/// If there are any fonts you don't want to appear, specify them here. By default, "Bodoni Ornaments", "Damascus" & "Hiragino" are excluded as they render in an odd way, with bits chopped off. | ||
/// To reinstate them, specify an empty array here | ||
/// - Parameter fontNames: the names of the fonts you want to add | ||
public func excludedFontNames(_ fontNames: [String]) -> Self { | ||
var copy = self | ||
copy.excludedFontNames = fontNames | ||
return copy | ||
} | ||
} | ||
|
||
|
||
extension View { | ||
|
||
/// View extension in the style of .sheet - lacks a couple of customisation options. If more flexibility is required, use FontPicker(...) directly, and apply the required modifiers | ||
/// - Parameters: | ||
/// - isPresented: binding to a Bool which controls whether or not to show the picker | ||
/// - selected: binding to a String for the selected font name | ||
func fontPicker(isPresented: Binding<Bool>, selected: Binding<String>) -> some View { | ||
modifier(FontPickerPresentationModifier(content: { FontPicker(isPresented: isPresented, selected: selected)})) | ||
} | ||
} | ||
|
||
|
||
struct FontPickerPresentationModifier: ViewModifier { | ||
|
||
var content: () -> FontPicker | ||
|
||
init(@ViewBuilder content: @escaping () -> FontPicker) { | ||
self.content = content | ||
} | ||
|
||
func body(content: Content) -> some View { | ||
self.content() | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// | ||
// FontPicker.swift | ||
// HandyList | ||
// | ||
// Created by Franklyn Weber on 28/01/2021. | ||
// | ||
|
||
import SwiftUI | ||
import HalfASheet | ||
|
||
|
||
struct FontPicker: View { | ||
|
||
@Binding private var isPresented: Bool | ||
@Binding private var selection: String | ||
|
||
internal var userFontNames: [String]? | ||
internal var additionalFontNames: [String] = [] | ||
|
||
// these fonts render in an odd way, with tops or bottoms being chopped off, or being nonsense for our purposes (such as symbols) | ||
// However, if the user wants them, they just need to specify [] as the excludedFontNames | ||
internal var excludedFontNames = [ | ||
"Bodoni Ornaments", | ||
"Damascus", | ||
"Hiragino" | ||
] | ||
|
||
internal var backgroundColor: UIColor = .systemBackground | ||
internal var _dismissOnSelection = true | ||
|
||
|
||
/// Initialiser | ||
/// - Parameters: | ||
/// - isPresented: binding to a Bool which controls whether or not to show the picker | ||
/// - selected: binding to a String for the selected font name | ||
init(isPresented: Binding<Bool>, selected: Binding<String>) { | ||
_isPresented = isPresented | ||
_selection = selected | ||
} | ||
|
||
var body: some View { | ||
|
||
HalfASheet(isPresented: $isPresented, title: "Font") { | ||
|
||
ZStack { | ||
|
||
RoundedRectangle(cornerRadius: 10) | ||
.foregroundColor(Color(UIColor.lightGray.withAlphaComponent(0.2))) | ||
RoundedRectangle(cornerRadius: 10) | ||
.foregroundColor(Color(backgroundColor)) | ||
|
||
List { | ||
ForEach(fontNamesToDisplay(), id: \.self) { fontName in | ||
|
||
HStack { | ||
Text(fontName) | ||
.customFont(name: fontName) | ||
Spacer() | ||
} | ||
.contentShape(Rectangle()) | ||
.onTapGesture { | ||
selection = fontName | ||
if _dismissOnSelection { | ||
isPresented = false | ||
} | ||
} | ||
} | ||
.listRowBackground(Color.clear) | ||
} | ||
} | ||
.onAppear { | ||
NotificationCenter.default.post(name: .fontPickerAppeared, object: self) | ||
} | ||
.onDisappear { | ||
NotificationCenter.default.post(name: .fontPickerDisappeared, object: self) | ||
} | ||
} | ||
.backgroundColor(backgroundColor) | ||
.closeButtonColor(UIColor.gray.withAlphaComponent(0.4)) | ||
.disableDragToDismiss | ||
} | ||
|
||
private func fontNamesToDisplay() -> [String] { | ||
|
||
if let userFontNames = userFontNames { | ||
return userFontNames | ||
} | ||
|
||
let fontNames = UIFont.familyNames.sorted().filter { !excludedFontNames.contains(where: $0.contains) } | ||
|
||
return (fontNames + additionalFontNames).sorted() | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// | ||
// CustomFont.swift | ||
// | ||
// Created by Franklyn on 25/06/2019. | ||
// Copyright © 2019 Franklyn. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
|
||
|
||
struct CustomFont: ViewModifier { | ||
|
||
let name: String | ||
let size: CGFloat? | ||
let style: Font.TextStyle? | ||
let weight: Font.Weight | ||
let maxSize: CGFloat? | ||
|
||
init(name: String, size: CGFloat? = nil, weight: Font.Weight = .regular, relativeTo style: Font.TextStyle? = nil) { | ||
self.name = name | ||
self.style = style | ||
self.size = size | ||
self.weight = weight | ||
maxSize = nil | ||
} | ||
|
||
init(name: String, weight: Font.Weight = .regular, relativeTo style: Font.TextStyle, maxSize: CGFloat) { | ||
self.name = name | ||
self.weight = weight | ||
self.maxSize = maxSize | ||
self.style = style | ||
size = nil | ||
} | ||
|
||
|
||
/// Will trigger the refresh of the view when the ContentSizeCategory changes. | ||
@Environment(\.sizeCategory) var sizeCategory: ContentSizeCategory | ||
|
||
func body(content: Content) -> some View { | ||
|
||
if let maxSize = maxSize, let style = style { | ||
let fontSize = min(Self.textSize(for: style), maxSize) | ||
return content.font(Font.custom(self.name, size: Self.scaledSize(for: fontSize, style: style)).weight(weight)) | ||
} | ||
|
||
if let size = self.size { | ||
if let style = style { | ||
return content.font(Font.custom(name, size: size, relativeTo: style).weight(weight)) | ||
} else { | ||
return content.font(Font.custom(name, size: size).weight(weight)) | ||
} | ||
} | ||
|
||
guard let style = self.style else { | ||
return content.font(Font.custom(name, size: Self.textSize(for: .body)).weight(weight)) | ||
} | ||
guard let size = self.fontSizes[style] else { | ||
return content.font(Font.custom(name, size: Self.textSize(for: .body)).weight(weight)) | ||
} | ||
|
||
return content.font(Font.custom(self.name, size: size, relativeTo: .body).weight(weight)) | ||
} | ||
|
||
|
||
private let fontSizes: [Font.TextStyle: CGFloat] = [ | ||
.largeTitle: 34, | ||
.title: 28, | ||
.title2: 22, | ||
.title3: 20, | ||
.headline: 17, | ||
.body: 17, | ||
.callout: 16, | ||
.subheadline: 15, | ||
.footnote: 13, | ||
.caption: 12, | ||
.caption2: 11 | ||
] | ||
|
||
private static func scaledSize(for size: CGFloat, style: Font.TextStyle) -> CGFloat { | ||
let scale = UIFontMetrics.default.scaledValue(for: size) | ||
return size * size / scale | ||
} | ||
|
||
private static func textSize(for textStyle: Font.TextStyle) -> CGFloat { | ||
return UIFont.preferredFont(style: textStyle.uiStyle).pointSize | ||
} | ||
} | ||
|
||
|
||
extension Text { | ||
|
||
func customFont(name: String, size: CGFloat? = nil, weight: Font.Weight = .regular, relativeTo style: Font.TextStyle? = nil) -> ModifiedContent<Self, CustomFont> { | ||
return modifier(CustomFont(name: name, size: size, weight: weight, relativeTo: style)) | ||
} | ||
|
||
func customFont(name: String, weight: Font.Weight = .regular, relativeTo style: Font.TextStyle, maxSize: CGFloat) -> ModifiedContent<Self, CustomFont> { | ||
return modifier(CustomFont(name: name, weight: weight, relativeTo: style, maxSize: maxSize)) | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
Sources/FontPicker/Helpers/Font.TextStyle+Extensions.swift
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// Font.TextStyle+Extensions.swift | ||
// | ||
// Created by Franklyn Weber on 02/02/2021. | ||
// | ||
|
||
import SwiftUI | ||
|
||
|
||
extension Font.TextStyle { | ||
|
||
var uiStyle: UIFont.TextStyle { | ||
switch self { | ||
case .largeTitle: return .largeTitle | ||
case .title: return .title1 | ||
case .title2: return .title2 | ||
case .title3: return .title3 | ||
case .headline: return .headline | ||
case .body: return .body | ||
case .callout: return .callout | ||
case .subheadline: return .subheadline | ||
case .footnote: return .footnote | ||
case .caption: return .caption1 | ||
case .caption2: return .caption2 | ||
@unknown default: | ||
return .body | ||
} | ||
} | ||
} | ||
|
||
|
||
extension Font.Weight { | ||
|
||
var uiWeight: UIFont.Weight { | ||
switch self { | ||
case .thin: return .thin | ||
case .light: return .light | ||
case .regular: return .regular | ||
case .medium: return .medium | ||
case .semibold: return .semibold | ||
case .bold: return .bold | ||
case .heavy: return .heavy | ||
case .black: return .black | ||
default: return .regular | ||
} | ||
} | ||
} |
Oops, something went wrong.