From d2e6d1e96a9ac1b00c8b3283671f1baf1f93cf1b Mon Sep 17 00:00:00 2001 From: Merrick Sapsford Date: Mon, 8 Mar 2021 11:00:21 +0100 Subject: [PATCH] Add support for Dynamic Type (#560) * Clean up * Add adjustsFontForContentSizeCategory to AnimateableLabel * Add adjustsFontForContentSizeCategory properties * Enable dynamic type in example * Require iOS 11 * Update TMLabelBarButton default font * Update TMTabItemBarButton default font * Fix constraint warnings --- CHANGELOG.md | 8 +++ .../BarButton/Types/TMLabelBarButton.swift | 14 ++++- .../BarButton/Types/TMTabItemBarButton.swift | 28 ++++++++-- .../Tabman/Bar/Generic/AnimateableLabel.swift | 55 ++++++++++++++++--- Sources/iOS/TabViewController.swift | 3 + 5 files changed, 93 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eefb842a..aaefb182 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,14 @@ All notable changes to this project will be documented in this file. - `0.5.x` Releases - [0.5.0](#050) | [0.5.1](#051) | [0.5.2](#052) | [0.5.3](#053) - `0.4.x` Releases - [0.4.0](#040) | [0.4.1](#041) | [0.4.2](#042) | [0.4.3](#043) | [0.4.4](#044) | [0.4.5](#045) | [0.4.6](#046) | [0.4.7](#047) | [0.4.8](#048) +--- +## [2.11.0](https://github.com/uias/Tabman/releases/tag/2.11.0) +Released on 2021-03-XX + +#### Added +- Support for Dynamic Type to `TMLabelBarButton` with `adjustsFontForContentSizeCategory`. +- Support for Dynamic Type to `TMTabItemBarButton` with `adjustsFontForContentSizeCategory`. + --- ## [2.10.0](https://github.com/uias/Tabman/releases/tag/2.10.0) Released on 2021-01-23 diff --git a/Sources/Tabman/Bar/BarButton/Types/TMLabelBarButton.swift b/Sources/Tabman/Bar/BarButton/Types/TMLabelBarButton.swift index d37e8bb6..8aa32b79 100644 --- a/Sources/Tabman/Bar/BarButton/Types/TMLabelBarButton.swift +++ b/Sources/Tabman/Bar/BarButton/Types/TMLabelBarButton.swift @@ -17,7 +17,7 @@ open class TMLabelBarButton: TMBarButton { private struct Defaults { static let contentInset = UIEdgeInsets(top: 12.0, left: 0.0, bottom: 12.0, right: 0.0) - static let font = UIFont.systemFont(ofSize: 17.0, weight: .semibold) + static let font = UIFont.preferredFont(forTextStyle: .headline) static let text = "Item" static let badgeLeadingInset: CGFloat = 8.0 } @@ -104,6 +104,18 @@ open class TMLabelBarButton: TMBarButton { label.font = selectedFont } } + /// A Boolean that indicates whether the object automatically updates its font when the device's content size category changes. + /// + /// Defaults to `false`. + @available(iOS 11, *) + open var adjustsFontForContentSizeCategory: Bool { + get { + label.adjustsFontForContentSizeCategory + } + set { + label.adjustsFontForContentSizeCategory = newValue + } + } /// How to vertically align the label within the button. Defaults to `.center`. /// diff --git a/Sources/Tabman/Bar/BarButton/Types/TMTabItemBarButton.swift b/Sources/Tabman/Bar/BarButton/Types/TMTabItemBarButton.swift index 44d5f243..87bb8930 100644 --- a/Sources/Tabman/Bar/BarButton/Types/TMTabItemBarButton.swift +++ b/Sources/Tabman/Bar/BarButton/Types/TMTabItemBarButton.swift @@ -69,6 +69,18 @@ open class TMTabItemBarButton: TMBarButton { label.font = font } } + /// A Boolean that indicates whether the object automatically updates its font when the device's content size category changes. + /// + /// Defaults to `false`. + @available(iOS 11, *) + open var adjustsFontForContentSizeCategory: Bool { + get { + label.adjustsFontForContentSizeCategory + } + set { + label.adjustsFontForContentSizeCategory = newValue + } + } /// Content Mode for the image view. open var imageContentMode: UIView.ContentMode { get { @@ -92,7 +104,7 @@ open class TMTabItemBarButton: TMBarButton { } } - // MARK: Lifecycle + // MARK: Init public required init(for item: TMBarItemable, intrinsicSuperview: UIView?) { super.init(for: item, intrinsicSuperview: intrinsicSuperview) @@ -106,6 +118,8 @@ open class TMTabItemBarButton: TMBarButton { super.init(coder: aDecoder) } + // MARK: Lifecycle + open override func layout(in view: UIView) { super.layout(in: view) @@ -263,13 +277,17 @@ open class TMTabItemBarButton: TMBarButton { ]) // Label / Image + let labelTrailing = container.trailingAnchor.constraint(equalTo: label.trailingAnchor, constant: labelPadding) + labelTrailing.priority = .init(999) + let imageViewLeading = imageView.leadingAnchor.constraint(greaterThanOrEqualTo: container.leadingAnchor, constant: imagePadding) + imageViewLeading.priority = .init(999) constraints.append(contentsOf: [ imageView.topAnchor.constraint(equalTo: container.topAnchor, constant: imagePadding), imageView.centerXAnchor.constraint(equalTo: container.centerXAnchor), - imageView.leadingAnchor.constraint(greaterThanOrEqualTo: container.leadingAnchor, constant: imagePadding), + imageViewLeading, label.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: Defaults.labelTopPadding), label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: labelPadding), - container.trailingAnchor.constraint(equalTo: label.trailingAnchor, constant: labelPadding), + labelTrailing, label.bottomAnchor.constraint(equalTo: container.bottomAnchor) ]) @@ -288,9 +306,9 @@ extension TMTabItemBarButton { private func defaultFont(for device: UIDevice) -> UIFont { switch device.userInterfaceIdiom { case .pad: - return UIFont.systemFont(ofSize: 14.0, weight: .medium) + return UIFont.preferredFont(forTextStyle: .caption1) default: - return UIFont.systemFont(ofSize: 10.0, weight: .medium) + return UIFont.preferredFont(forTextStyle: .caption2) } } } diff --git a/Sources/Tabman/Bar/Generic/AnimateableLabel.swift b/Sources/Tabman/Bar/Generic/AnimateableLabel.swift index f70e1dd7..f6503d4a 100644 --- a/Sources/Tabman/Bar/Generic/AnimateableLabel.swift +++ b/Sources/Tabman/Bar/Generic/AnimateableLabel.swift @@ -39,11 +39,7 @@ internal class AnimateableLabel: UIView { } var font: UIFont? { didSet { - textLayer.font = font - textLayer.fontSize = font?.pointSize ?? 17.0 - invalidateIntrinsicContentSize() - superview?.setNeedsLayout() - superview?.layoutIfNeeded() + reloadTextLayerForCurrentFont() } } var textAlignment: NSTextAlignment? { @@ -52,30 +48,71 @@ internal class AnimateableLabel: UIView { } } + private var _adjustsFontForContentSizeCategory = false + /// A Boolean that indicates whether the object automatically updates its font when the device's content size category changes. + /// + /// Defaults to `false`. + @available(iOS 11, *) + var adjustsFontForContentSizeCategory: Bool { + get { + _adjustsFontForContentSizeCategory + } + set { + _adjustsFontForContentSizeCategory = newValue + reloadTextLayerForCurrentFont() + } + } + // MARK: Init override init(frame: CGRect) { super.init(frame: frame) - initialize() + commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - initialize() + commonInit() } - private func initialize() { + private func commonInit() { textLayer.truncationMode = .end textLayer.contentsScale = UIScreen.main.scale layer.addSublayer(textLayer) } + // MARK: Lifecycle + override func layoutSubviews() { super.layoutSubviews() - textLayer.frame = bounds } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + if #available(iOS 10, *) { + guard traitCollection.preferredContentSizeCategory != previousTraitCollection?.preferredContentSizeCategory else { + return + } + reloadTextLayerForCurrentFont() + } + } + + private func reloadTextLayerForCurrentFont() { + if #available(iOS 11, *), adjustsFontForContentSizeCategory, let font = font, let textStyle = font.fontDescriptor.object(forKey: .textStyle) as? UIFont.TextStyle { + let font = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: font) + textLayer.font = font + textLayer.fontSize = font.pointSize + } else { + textLayer.font = font + textLayer.fontSize = font?.pointSize ?? 17.0 + } + invalidateIntrinsicContentSize() + superview?.setNeedsLayout() + superview?.layoutIfNeeded() + } } private extension AnimateableLabel { diff --git a/Sources/iOS/TabViewController.swift b/Sources/iOS/TabViewController.swift index 389ab67d..a09be407 100644 --- a/Sources/iOS/TabViewController.swift +++ b/Sources/iOS/TabViewController.swift @@ -45,6 +45,9 @@ class TabViewController: TabmanViewController, PageboyViewControllerDataSource, bar.buttons.customize { $0.tintColor = UIColor.tabmanForeground.withAlphaComponent(0.4) $0.selectedTintColor = .tabmanForeground + if #available(iOS 11, *) { + $0.adjustsFontForContentSizeCategory = true + } } bar.indicator.tintColor = .tabmanForeground