Skip to content

Commit

Permalink
Add support for custom font
Browse files Browse the repository at this point in the history
Silence iPad constraint errors
  • Loading branch information
lascic committed Aug 8, 2023
1 parent d914130 commit 7b3d512
Show file tree
Hide file tree
Showing 29 changed files with 395 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"location" : "https://github.com/lascic/UIOnboarding.git",
"state" : {
"branch" : "main",
"revision" : "de7d408b49fe5992303a20f070c9ea3d405eeee5"
"revision" : "84ac395bc58893ca524fa11265482e71768142f6"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
0BD28DF627BEDE9B00D768E6 /* UIOnboardingOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD28DE127BEDE9B00D768E6 /* UIOnboardingOverlay.swift */; };
0BD28DF727BEDE9B00D768E6 /* UIOnboardingTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD28DE227BEDE9B00D768E6 /* UIOnboardingTextView.swift */; };
0BD28DF927BEDF7D00D768E6 /* UIOnboardingHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD28DF827BEDF7D00D768E6 /* UIOnboardingHelper.swift */; };
C6C5A8552A8180A900E71BF5 /* UIIntrinsicLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C5A8542A8180A900E71BF5 /* UIIntrinsicLabel.swift */; };
DCB303DC2853517B002AC325 /* UIOnboardingTitleLabelStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCB303DB2853517B002AC325 /* UIOnboardingTitleLabelStack.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -67,6 +68,7 @@
0BD28DE127BEDE9B00D768E6 /* UIOnboardingOverlay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIOnboardingOverlay.swift; sourceTree = "<group>"; };
0BD28DE227BEDE9B00D768E6 /* UIOnboardingTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIOnboardingTextView.swift; sourceTree = "<group>"; };
0BD28DF827BEDF7D00D768E6 /* UIOnboardingHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIOnboardingHelper.swift; sourceTree = "<group>"; };
C6C5A8542A8180A900E71BF5 /* UIIntrinsicLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIIntrinsicLabel.swift; sourceTree = "<group>"; };
DCB303DB2853517B002AC325 /* UIOnboardingTitleLabelStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIOnboardingTitleLabelStack.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -162,6 +164,7 @@
children = (
0BD28DDE27BEDE9B00D768E6 /* UIOnboardingIcon.swift */,
0BD28DDF27BEDE9B00D768E6 /* UIOnboardingTitleLabel.swift */,
C6C5A8542A8180A900E71BF5 /* UIIntrinsicLabel.swift */,
DCB303DB2853517B002AC325 /* UIOnboardingTitleLabelStack.swift */,
0BD28DDB27BEDE9B00D768E6 /* UIOnboardingStack.swift */,
0BD28DDC27BEDE9B00D768E6 /* UIIntrinsicTableView.swift */,
Expand Down Expand Up @@ -248,6 +251,7 @@
0BD28DF527BEDE9B00D768E6 /* UIOnboardingButton.swift in Sources */,
0BD28DEE27BEDE9B00D768E6 /* UIViewController+Ext.swift in Sources */,
0BD28DE827BEDE9B00D768E6 /* UIScreenType.swift in Sources */,
C6C5A8552A8180A900E71BF5 /* UIIntrinsicLabel.swift in Sources */,
0BD28DF227BEDE9B00D768E6 /* UIOnboardingCell.swift in Sources */,
0BD28DF727BEDE9B00D768E6 /* UIOnboardingTextView.swift in Sources */,
0BD28DF627BEDE9B00D768E6 /* UIOnboardingOverlay.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import UIKit

struct UIOnboardingButtonConfiguration {
var title: String
var fontName: String
var titleColor: UIColor
var backgroundColor: UIColor

init(title: String,
fontName: String = "",
titleColor: UIColor = .white,
backgroundColor: UIColor) {
self.title = title
self.fontName = fontName
self.titleColor = titleColor
self.backgroundColor = backgroundColor
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,19 @@ struct UIOnboardingFeature {
self.description = description
}
}

struct UIOnboardingFeatureStyle {
var titleFontName: String
var titleFontSize: CGFloat
var descriptionFontName: String
var descriptionFontSize: CGFloat
var spacing: CGFloat

init(titleFontName: String = "", titleFontSize: CGFloat = 17, descriptionFontName: String = "", descriptionFontSize: CGFloat = 17, spacing: CGFloat = 0.8) {
self.titleFontName = titleFontName
self.titleFontSize = titleFontSize
self.descriptionFontName = descriptionFontName
self.descriptionFontSize = descriptionFontSize
self.spacing = spacing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@ struct UIOnboardingTextViewConfiguration {
var icon: UIImage?
var text: String
var linkTitle: String?
var fontName: String
var link: String?
var tint: UIColor?

init(icon: UIImage? = nil,
text: String,
linkTitle: String? = nil,
fontName: String = "",
link: String? = nil,
tint: UIColor? = nil) {
self.icon = icon
self.text = text
self.linkTitle = linkTitle
self.fontName = fontName
self.link = link
self.tint = tint
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ struct UIOnboardingViewConfiguration {
var firstTitleLine: NSMutableAttributedString
var secondTitleLine: NSMutableAttributedString
var features: Array<UIOnboardingFeature>
let featureStyle: UIOnboardingFeatureStyle
var textViewConfiguration: UIOnboardingTextViewConfiguration? = nil
var buttonConfiguration: UIOnboardingButtonConfiguration

init(appIcon: UIImage,
firstTitleLine: NSMutableAttributedString,
secondTitleLine: NSMutableAttributedString,
features: Array<UIOnboardingFeature>,
featureStyle: UIOnboardingFeatureStyle = .init(),
textViewConfiguration: UIOnboardingTextViewConfiguration? = nil,
buttonConfiguration: UIOnboardingButtonConfiguration) {
self.appIcon = appIcon
self.firstTitleLine = firstTitleLine
self.secondTitleLine = secondTitleLine
self.features = features
self.featureStyle = featureStyle
self.textViewConfiguration = textViewConfiguration
self.buttonConfiguration = buttonConfiguration
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ final class UIOnboardingViewController: UIViewController {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

deinit {
print("UIOnboardingViewController: deinit {}")
}


override func viewDidLoad() {
super.viewDidLoad()
view.isUserInteractionEnabled = false
Expand Down Expand Up @@ -95,17 +91,12 @@ final class UIOnboardingViewController: UIViewController {
}

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
onboardingStackView.onboardingTitleLabelStack.setFont(font: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 80 : (UIScreenType.isiPhoneSE || UIScreenType.isiPhone6s ? 41 : 44), weight: .heavy))
onboardingStackView.onboardingTitleLabelStack.configureFont(traitCollection.horizontalSizeClass == .regular ? 80 : (UIScreenType.isiPhoneSE || UIScreenType.isiPhone6s ? 41 : 44))

continueButtonHeight.constant = UIFontMetrics.default.scaledValue(for: traitCollection.horizontalSizeClass == .regular ? 50 : (UIScreenType.isiPhoneSE ? 48 : 52))
continueButton.titleLabel?.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 19 : 17, weight: .bold))
continueButton.configureFont()

if #available(iOS 15.0, *) {
onboardingTextView?.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 15 : 13))
onboardingTextView?.maximumContentSizeCategory = .accessibilityMedium
} else {
onboardingTextView?.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 15 : 13), maximumPointSize: traitCollection.horizontalSizeClass == .regular ? 21 : 19)
}
onboardingTextView?.configureFont()
needsUIRefresh = true
onboardingTextView?.layoutIfNeeded()
continueButton.layoutIfNeeded()
Expand Down Expand Up @@ -162,7 +153,7 @@ private extension UIOnboardingViewController {
onboardingStackView.topAnchor.constraint(equalTo: onboardingScrollView.topAnchor).isActive = true
onboardingStackView.bottomAnchor.constraint(equalTo: onboardingScrollView.bottomAnchor).isActive = true

onboardingStackViewWidth = onboardingStackView.widthAnchor.constraint(equalToConstant: traitCollection.horizontalSizeClass == .regular ? 480 : view.frame.width - (UIScreenType.setUpPadding() * 2))
onboardingStackViewWidth = onboardingStackView.widthAnchor.constraint(equalToConstant: (traitCollection.horizontalSizeClass == .regular && traitCollection.userInterfaceIdiom == .pad) ? 480 : view.frame.width - (UIScreenType.setUpPadding() * 2))
onboardingStackViewWidth.isActive = true
onboardingStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// UIIntrinsicLabel.swift
// UIOnboarding Demo
//
// Created by Lukman Aščić on 07.08.23.
//

import UIKit

class UIIntrinsicLabel: UILabel {
private let gutter: CGFloat = 4

override func draw(_ rect: CGRect) {
super.drawText(in: rect.insetBy(dx: gutter, dy: 0))
}

override var alignmentRectInsets: UIEdgeInsets {
.init(top: 0, left: gutter, bottom: 0, right: gutter)
}

override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
size.width += gutter * 2
return size
}

override func sizeThatFits(_ size: CGSize) -> CGSize {
let fixedSize: CGSize = .init(width: size.width - 2 * gutter, height: size.height)
let sizeWithoutGutter: CGSize = super.sizeThatFits(fixedSize)
return .init(width: sizeWithoutGutter.width + 2 * gutter, height: sizeWithoutGutter.height)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ class UIIntrinsicTableView: UITableView {

override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return .init(width: UIView.noIntrinsicMetric, height: contentSize.height)
return .init(width: .zero, height: contentSize.height)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import UIKit

final class UIOnboardingButton: UIButton {
weak var delegate: UIOnboardingButtonDelegate?
private var fontName: String = ""

convenience init(withConfiguration configuration: UIOnboardingButtonConfiguration) {
self.init(type: .system)
fontName = configuration.fontName
configureFont()
setTitle(configuration.title, for: .normal)

#if !targetEnvironment(macCatalyst)
Expand All @@ -29,7 +32,7 @@ final class UIOnboardingButton: UIButton {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func configure() {
layer.cornerRadius = UIScreenType.isiPhoneSE ? 13 : 15
layer.cornerCurve = .continuous
Expand All @@ -45,7 +48,6 @@ final class UIOnboardingButton: UIButton {
isPointerInteractionEnabled = true
}

titleLabel?.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 19 : 17, weight: .bold))
addTarget(self, action: #selector(handleCallToActionButton), for: .touchUpInside)
}

Expand All @@ -57,3 +59,14 @@ final class UIOnboardingButton: UIButton {
protocol UIOnboardingButtonDelegate: AnyObject {
func didPressContinueButton()
}

extension UIOnboardingButton {
func configureFont() {
if let customFont = UIFont(name: fontName, size: traitCollection.horizontalSizeClass == .regular ? 19 : 17) {
let dynamicCustomFont = UIFontMetrics.default.scaledFont(for: customFont)
titleLabel?.font = dynamicCustomFont
} else {
titleLabel?.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 19 : 17, weight: .bold))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ final class UIOnboardingCell: UITableViewCell {
return featureGlyph
}()

private let titleLabel: UILabel = {
let label: UILabel = .init()
private let titleLabel: UIIntrinsicLabel = {
let label: UIIntrinsicLabel = .init()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping

Expand All @@ -39,8 +39,8 @@ final class UIOnboardingCell: UITableViewCell {
private var stackLeading: NSLayoutConstraint!
private var stackBottom: NSLayoutConstraint!

private let descriptionLabel: UILabel = {
let label: UILabel = .init()
private let descriptionLabel: UIIntrinsicLabel = {
let label: UIIntrinsicLabel = .init()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping

Expand All @@ -52,34 +52,34 @@ final class UIOnboardingCell: UITableViewCell {
}()

private var labelStack: UIStackView!

var configuration: UIOnboardingFeatureStyle = .init()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
configure()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func configure() {
func configure(feature: UIOnboardingFeature) {
backgroundColor = .clear
contentView.backgroundColor = .clear

selectionStyle = .none

isAccessibilityElement = false
titleLabel.isAccessibilityElement = true
titleLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 20 : 17, weight: .semibold))

descriptionLabel.isAccessibilityElement = true
descriptionLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 20 : 17, weight: .light))

configureFonts()

labelStack = .init(frame: .zero)
labelStack.axis = .vertical
labelStack.addArrangedSubview(titleLabel)
labelStack.addArrangedSubview(descriptionLabel)
labelStack.setCustomSpacing(0.8, after: titleLabel)
labelStack.setCustomSpacing(configuration.spacing, after: titleLabel)
labelStack.translatesAutoresizingMaskIntoConstraints = false

contentView.addSubview(featureGlyph)
Expand All @@ -97,9 +97,11 @@ final class UIOnboardingCell: UITableViewCell {

featureGlyph.topAnchor.constraint(equalTo: titleLabel.topAnchor, constant: 4).isActive = true
contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: 44).isActive = true

set(feature)
}

func set(_ feature: UIOnboardingFeature) {
private func set(_ feature: UIOnboardingFeature) {
featureGlyph.image = feature.icon
featureGlyph.tintColor = feature.iconTint

Expand All @@ -111,12 +113,27 @@ final class UIOnboardingCell: UITableViewCell {
}

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
titleLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 20 : 17, weight: .semibold))
descriptionLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? 20 : 17, weight: .light))
configureFonts()

stackBottom.constant = traitCollection.horizontalSizeClass == .regular ? -48 : -12
featureGlyphWidth.constant = traitCollection.horizontalSizeClass == .regular ? 60 : 44
stackLeading.constant = traitCollection.horizontalSizeClass == .regular ? 32 : 18
contentView.layoutIfNeeded()
}
}

private extension UIOnboardingCell {
func configureFonts() {
if let customTitleFont = UIFont(name: configuration.titleFontName, size: traitCollection.horizontalSizeClass == .regular ? configuration.titleFontSize * 1.176 : configuration.titleFontSize) {
titleLabel.font = UIFontMetrics.default.scaledFont(for: customTitleFont)
} else {
titleLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? configuration.titleFontSize * 1.176 : configuration.titleFontSize, weight: .semibold))
}

if let customDescriptionFont = UIFont(name: configuration.descriptionFontName, size: traitCollection.horizontalSizeClass == .regular ? configuration.descriptionFontSize * 1.176 : configuration.descriptionFontSize) {
descriptionLabel.font = UIFontMetrics.default.scaledFont(for: customDescriptionFont)
} else {
descriptionLabel.font = UIFontMetrics.default.scaledFont(for: .systemFont(ofSize: traitCollection.horizontalSizeClass == .regular ? configuration.descriptionFontSize * 1.176 : configuration.descriptionFontSize, weight: .light))
}
}
}
Loading

0 comments on commit 7b3d512

Please sign in to comment.