Layout improvements

This commit is contained in:
Kyle Bashour 2022-11-27 21:00:03 -08:00
parent 459564ae6b
commit 61a07e9a5b
1 changed files with 64 additions and 39 deletions

View File

@ -23,22 +23,8 @@ public final class StatusCardControl: UIControl {
private let titleLabel = UILabel() private let titleLabel = UILabel()
private let linkLabel = UILabel() private let linkLabel = UILabel()
private lazy var compactImageConstraints = [ private var layout: Layout?
imageView.heightAnchor.constraint(equalTo: heightAnchor), private var layoutConstraints: [NSLayoutConstraint] = []
imageView.widthAnchor.constraint(equalToConstant: 85),
heightAnchor.constraint(equalToConstant: 85).priority(.defaultLow - 1),
heightAnchor.constraint(greaterThanOrEqualToConstant: 85)
]
private lazy var largeImageConstraints = [
imageView.heightAnchor.constraint(
equalTo: imageView.widthAnchor,
multiplier: 21 / 40
)
// This priority is important or constraints break;
// it still renders the card correctly.
.priority(.defaultLow - 1),
]
public override var isHighlighted: Bool { public override var isHighlighted: Bool {
didSet { highlightView.isHidden = !isHighlighted } didSet { highlightView.isHidden = !isHighlighted }
@ -85,6 +71,7 @@ public final class StatusCardControl: UIControl {
labelStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10) labelStackView.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10)
labelStackView.isLayoutMarginsRelativeArrangement = true labelStackView.isLayoutMarginsRelativeArrangement = true
labelStackView.axis = .vertical labelStackView.axis = .vertical
labelStackView.spacing = 2
containerStackView.addArrangedSubview(imageView) containerStackView.addArrangedSubview(imageView)
containerStackView.addArrangedSubview(labelStackView) containerStackView.addArrangedSubview(labelStackView)
@ -106,8 +93,6 @@ public final class StatusCardControl: UIControl {
} }
public func configure(card: Card) { public func configure(card: Card) {
let isCompact = card.width == card.height
if let host = card.url?.host { if let host = card.url?.host {
accessibilityLabel = "\(card.title) \(host)" accessibilityLabel = "\(card.title) \(host)"
} else { } else {
@ -120,26 +105,17 @@ public final class StatusCardControl: UIControl {
imageView.sd_setImage( imageView.sd_setImage(
with: card.imageURL, with: card.imageURL,
placeholderImage: isCompact ? newsIcon : photoIcon placeholderImage: icon(for: card.layout)
) { [weak imageView] image, _, _, _ in ) { [weak self] image, _, _, _ in
if image != nil { if image != nil {
imageView?.contentMode = .scaleAspectFill self?.imageView.contentMode = .scaleAspectFill
self.containerStackView.setNeedsLayout()
self.containerStackView.layoutIfNeeded()
}
} }
NSLayoutConstraint.deactivate(compactImageConstraints + largeImageConstraints) self?.containerStackView.setNeedsLayout()
self?.containerStackView.layoutIfNeeded()
if isCompact {
containerStackView.alignment = .center
containerStackView.axis = .horizontal
NSLayoutConstraint.activate(compactImageConstraints)
} else {
containerStackView.alignment = .fill
containerStackView.axis = .vertical
NSLayoutConstraint.activate(largeImageConstraints)
} }
updateConstraints(for: card.layout)
} }
public override func didMoveToWindow() { public override func didMoveToWindow() {
@ -150,14 +126,48 @@ public final class StatusCardControl: UIControl {
} }
} }
private var newsIcon: UIImage? { private func updateConstraints(for layout: Layout) {
UIImage(systemName: "newspaper.fill") guard layout != self.layout else { return }
self.layout = layout
NSLayoutConstraint.deactivate(layoutConstraints)
switch layout {
case .large(let aspectRatio):
containerStackView.alignment = .fill
containerStackView.axis = .vertical
layoutConstraints = [
imageView.widthAnchor.constraint(
equalTo: imageView.heightAnchor,
multiplier: aspectRatio
)
// This priority is important or constraints break;
// it still renders the card correctly.
.priority(.defaultLow - 1),
]
case .compact:
containerStackView.alignment = .center
containerStackView.axis = .horizontal
layoutConstraints = [
imageView.heightAnchor.constraint(equalTo: heightAnchor),
imageView.widthAnchor.constraint(equalToConstant: 85),
heightAnchor.constraint(equalToConstant: 85).priority(.defaultLow - 1),
heightAnchor.constraint(greaterThanOrEqualToConstant: 85)
]
} }
private var photoIcon: UIImage? { NSLayoutConstraint.activate(layoutConstraints)
}
private func icon(for layout: Layout) -> UIImage? {
switch layout {
case .compact:
return UIImage(systemName: "newspaper.fill")
case .large:
let configuration = UIImage.SymbolConfiguration(pointSize: 32) let configuration = UIImage.SymbolConfiguration(pointSize: 32)
return UIImage(systemName: "photo", withConfiguration: configuration) return UIImage(systemName: "photo", withConfiguration: configuration)
} }
}
private func apply(theme: Theme) { private func apply(theme: Theme) {
layer.borderColor = theme.separator.cgColor layer.borderColor = theme.separator.cgColor
@ -165,6 +175,21 @@ public final class StatusCardControl: UIControl {
} }
} }
private extension StatusCardControl {
enum Layout: Equatable {
case compact
case large(aspectRatio: CGFloat)
}
}
private extension Card {
var layout: StatusCardControl.Layout {
return width == height || image == nil
? .compact
: .large(aspectRatio: CGFloat(width) / CGFloat(height))
}
}
private extension UILayoutPriority { private extension UILayoutPriority {
static let zero = UILayoutPriority(rawValue: 0) static let zero = UILayoutPriority(rawValue: 0)
} }