Skip to content

Commit c236391

Browse files
authored
[Stats Revamp] Fixing Scaling Font (Dynamic Type) issues (#19790)
* Expand Add Stats Card view section height when dynamic type increases * Support dynamic type in chartView legends - Switch to vertical stack view when appropriate - Increase text size * Set maximum font sizes for data switcher element in Stats There's a limited space in a header that displays date in a date switcher. Set the maximum font sizes to support limited amount of text increase for a dynamic type. * Increase button title sizes automatically in Insights update prompt * Decrease maximum font size for charts in Views and Visitors * Improve chart view to support longer legend titles Using equalSpacing makes long titles go out of bounds. - Use fillEqually for each legend title to take same amount of space - Rebuild legend layout to support fillEqually distribution
1 parent 8f163a4 commit c236391

File tree

7 files changed

+98
-15
lines changed

7 files changed

+98
-15
lines changed

WordPress/Classes/ViewRelated/Gutenberg/Collapsable Header/CollapsableHeaderViewController.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,13 +410,15 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
410410
[defaultActionButton, secondaryActionButton].forEach { (button) in
411411
button?.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .medium)
412412
button?.titleLabel?.adjustsFontSizeToFitWidth = true
413+
button?.titleLabel?.adjustsFontForContentSizeCategory = true
413414
button?.layer.borderColor = seperator.cgColor
414415
button?.layer.borderWidth = 1
415416
button?.layer.cornerRadius = 8
416417
}
417418

418419
primaryActionButton.titleLabel?.font = WPStyleGuide.fontForTextStyle(.body, fontWeight: .medium)
419420
primaryActionButton.titleLabel?.adjustsFontSizeToFitWidth = true
421+
primaryActionButton.titleLabel?.adjustsFontForContentSizeCategory = true
420422
primaryActionButton.backgroundColor = accentColor
421423
primaryActionButton.layer.cornerRadius = 8
422424
}

WordPress/Classes/ViewRelated/Stats/Charts/DonutChartView.swift

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,12 @@ class DonutChartView: UIView {
7979
titleLabel = UILabel()
8080
titleLabel.textAlignment = .center
8181
titleLabel.font = .preferredFont(forTextStyle: .subheadline)
82+
titleLabel.adjustsFontForContentSizeCategory = true
8283

8384
totalCountLabel = UILabel()
8485
totalCountLabel.textAlignment = .center
8586
totalCountLabel.font = .preferredFont(forTextStyle: .title1).bold()
87+
totalCountLabel.adjustsFontForContentSizeCategory = true
8688

8789
titleStackView = UIStackView(arrangedSubviews: [titleLabel, totalCountLabel])
8890

@@ -97,7 +99,8 @@ class DonutChartView: UIView {
9799
legendStackView = UIStackView()
98100
legendStackView.translatesAutoresizingMaskIntoConstraints = false
99101
legendStackView.spacing = Constants.legendStackViewSpacing
100-
legendStackView.distribution = .equalSpacing
102+
legendStackView.distribution = .fillEqually
103+
legendStackView.alignment = .center
101104

102105
addSubview(legendStackView)
103106
}
@@ -107,6 +110,7 @@ class DonutChartView: UIView {
107110
chartContainer.leadingAnchor.constraint(equalTo: leadingAnchor),
108111
chartContainer.trailingAnchor.constraint(equalTo: trailingAnchor),
109112
chartContainer.topAnchor.constraint(equalTo: topAnchor),
113+
chartContainer.heightAnchor.constraint(equalToConstant: Constants.chartHeight),
110114

111115
legendStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
112116
legendStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
@@ -252,6 +256,22 @@ class DonutChartView: UIView {
252256
}
253257
}
254258

259+
// MARK: - Dynamic Type
260+
261+
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
262+
super.traitCollectionDidChange(previousTraitCollection)
263+
264+
if traitCollection.preferredContentSizeCategory.isAccessibilityCategory {
265+
legendStackView.axis = .vertical
266+
legendStackView.alignment = .leading
267+
legendStackView.subviews.forEach { ($0 as? LegendView)?.isCentered = false }
268+
} else {
269+
legendStackView.axis = .horizontal
270+
legendStackView.alignment = .center
271+
legendStackView.subviews.forEach { ($0 as? LegendView)?.isCentered = true }
272+
}
273+
}
274+
255275
// MARK: Helpers
256276

257277
private func makeSegmentLayer(_ segment: Segment) -> CAShapeLayer {
@@ -293,6 +313,7 @@ class DonutChartView: UIView {
293313
static let titleStackViewSpacing: CGFloat = 8.0
294314
static let legendStackViewSpacing: CGFloat = 8.0
295315
static let chartToLegendSpacing: CGFloat = 32.0
316+
static let chartHeight: CGFloat = 180.0
296317

297318
// We'll rotate the chart back by 90 degrees so it starts at the top rather than the right
298319
static let chartRotationDegrees: CGFloat = -90.0
@@ -307,6 +328,17 @@ class DonutChartView: UIView {
307328
private class LegendView: UIView {
308329
let segment: DonutChartView.Segment
309330

331+
var isCentered: Bool {
332+
get {
333+
return leadingConstraint?.isActive ?? false
334+
}
335+
336+
set {
337+
leadingConstraint?.isActive = !newValue
338+
}
339+
}
340+
private var leadingConstraint: NSLayoutConstraint?
341+
310342
init(segment: DonutChartView.Segment) {
311343
self.segment = segment
312344

@@ -320,27 +352,44 @@ private class LegendView: UIView {
320352
}
321353

322354
private func configureSubviews() {
355+
let containerView = UIView()
356+
containerView.translatesAutoresizingMaskIntoConstraints = false
357+
323358
let indicator = UIView()
324359
indicator.backgroundColor = segment.color
325360
indicator.layer.cornerRadius = 6.0
361+
indicator.translatesAutoresizingMaskIntoConstraints = false
326362

327363
let titleLabel = UILabel()
328-
titleLabel.font = .preferredFont(forTextStyle: .subheadline)
364+
titleLabel.font = .preferredFont(forTextStyle: .footnote)
365+
titleLabel.adjustsFontForContentSizeCategory = true
329366
titleLabel.text = segment.title
367+
titleLabel.translatesAutoresizingMaskIntoConstraints = false
368+
titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
369+
370+
containerView.addSubviews([titleLabel, indicator])
371+
addSubview(containerView)
330372

331-
let stackView = UIStackView(arrangedSubviews: [indicator, titleLabel])
332-
stackView.translatesAutoresizingMaskIntoConstraints = false
333-
stackView.spacing = 8.0
334-
addSubview(stackView)
373+
leadingConstraint = containerView.leadingAnchor.constraint(equalTo: leadingAnchor)
374+
leadingConstraint?.priority = .required
335375

336376
NSLayoutConstraint.activate([
337377
indicator.widthAnchor.constraint(equalToConstant: 12.0),
338378
indicator.heightAnchor.constraint(equalToConstant: 12.0),
339-
340-
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
341-
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
342-
stackView.topAnchor.constraint(equalTo: topAnchor),
343-
stackView.bottomAnchor.constraint(equalTo: bottomAnchor)
379+
indicator.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
380+
indicator.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
381+
382+
titleLabel.leadingAnchor.constraint(equalTo: indicator.trailingAnchor, constant: 8),
383+
titleLabel.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
384+
titleLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
385+
titleLabel.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor),
386+
titleLabel.bottomAnchor.constraint(lessThanOrEqualTo: containerView.bottomAnchor),
387+
388+
containerView.topAnchor.constraint(equalTo: topAnchor),
389+
containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
390+
containerView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor),
391+
containerView.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor),
392+
containerView.centerXAnchor.constraint(equalTo: centerXAnchor)
344393
])
345394
}
346395
}

WordPress/Classes/ViewRelated/Stats/Extensions/WPStyleGuide+Stats.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ extension WPStyleGuide {
206206

207207
// MARK: - Font Size
208208

209-
static let maximumChartAxisFontPointSize: CGFloat = 22
209+
static let maximumChartAxisFontPointSize: CGFloat = 18
210210

211211
// MARK: - Style Values
212212

WordPress/Classes/ViewRelated/Stats/Insights/Insights Management/InsightsManagementViewController.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class InsightsManagementViewController: UITableViewController {
6868
reloadViewModel()
6969
WPStyleGuide.configureColors(view: view, tableView: tableView)
7070
WPStyleGuide.configureAutomaticHeightRows(for: tableView)
71+
tableView.estimatedSectionHeaderHeight = 38
7172
tableView.accessibilityIdentifier = TextContent.title
7273

7374
if FeatureFlag.statsNewAppearance.enabled {
@@ -89,7 +90,7 @@ class InsightsManagementViewController: UITableViewController {
8990
// MARK: TableView Data Source / Delegate Overrides
9091

9192
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
92-
return 38
93+
return UITableView.automaticDimension
9394
}
9495

9596
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {

WordPress/Classes/ViewRelated/Stats/Shared Views/Date Chooser/SiteStatsTableHeaderView.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,17 @@ private extension SiteStatsTableHeaderView {
144144

145145
func applyStyles() {
146146
backgroundColor = .listForeground
147+
147148
Style.configureLabelAsCellRowTitle(dateLabel)
149+
dateLabel.font = Metrics.dateLabelFont
150+
dateLabel.adjustsFontForContentSizeCategory = true
151+
dateLabel.minimumScaleFactor = Metrics.minimumScaleFactor
152+
148153
Style.configureLabelAsChildRowTitle(timezoneLabel)
154+
timezoneLabel.font = Metrics.timezoneFont
155+
timezoneLabel.adjustsFontForContentSizeCategory = true
156+
timezoneLabel.minimumScaleFactor = Metrics.minimumScaleFactor
157+
149158
Style.configureViewAsSeparator(bottomSeparatorLine)
150159

151160
// Required as the Style separator configure method clears all
@@ -311,3 +320,25 @@ extension SiteStatsTableHeaderView: StatsBarChartViewDelegate {
311320
reloadView()
312321
}
313322
}
323+
324+
private extension SiteStatsTableHeaderView {
325+
enum Metrics {
326+
static let dateLabelFontSize: CGFloat = 20
327+
static let maximumDateLabelFontSize: CGFloat = 32
328+
static let timezoneFontSize: CGFloat = 16
329+
static let maximumTimezoneFontSize: CGFloat = 20
330+
static let minimumScaleFactor: CGFloat = 0.8
331+
332+
static var dateLabelFont: UIFont {
333+
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .headline)
334+
let font = UIFont(descriptor: fontDescriptor, size: dateLabelFontSize)
335+
return UIFontMetrics.default.scaledFont(for: font, maximumPointSize: maximumDateLabelFontSize)
336+
}
337+
338+
static var timezoneFont: UIFont {
339+
let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .callout)
340+
let font = UIFont(descriptor: fontDescriptor, size: timezoneFontSize)
341+
return UIFontMetrics.default.scaledFont(for: font, maximumPointSize: maximumTimezoneFontSize)
342+
}
343+
}
344+
}

WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsFollowersChartViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct StatsFollowersChartViewModel {
1515
let chartView = DonutChartView()
1616
chartView.configure(title: "", totalCount: CGFloat(totalCount()), segments: segments())
1717
chartView.translatesAutoresizingMaskIntoConstraints = false
18-
chartView.heightAnchor.constraint(equalToConstant: Constants.chartHeight).isActive = true
18+
chartView.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.chartHeight).isActive = true
1919
return chartView
2020
}
2121

WordPress/Classes/ViewRelated/Stats/Shared Views/Stats Detail/StatsReferrersChartViewModel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct StatsReferrersChartViewModel {
5353
let chartView = DonutChartView()
5454
chartView.configure(title: Constants.chartTitle, totalCount: CGFloat(referrers.totalReferrerViewsCount), segments: segments)
5555
chartView.translatesAutoresizingMaskIntoConstraints = false
56-
chartView.heightAnchor.constraint(equalToConstant: Constants.chartHeight).isActive = true
56+
chartView.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.chartHeight).isActive = true
5757
return chartView
5858
}
5959

0 commit comments

Comments
 (0)