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 linkLabel = UILabel()
private lazy var compactImageConstraints = [
imageView.heightAnchor.constraint(equalTo: heightAnchor),
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),
]
private var layout: Layout?
private var layoutConstraints: [NSLayoutConstraint] = []
public override var isHighlighted: Bool {
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.isLayoutMarginsRelativeArrangement = true
labelStackView.axis = .vertical
labelStackView.spacing = 2
containerStackView.addArrangedSubview(imageView)
containerStackView.addArrangedSubview(labelStackView)
@ -106,8 +93,6 @@ public final class StatusCardControl: UIControl {
}
public func configure(card: Card) {
let isCompact = card.width == card.height
if let host = card.url?.host {
accessibilityLabel = "\(card.title) \(host)"
} else {
@ -120,26 +105,17 @@ public final class StatusCardControl: UIControl {
imageView.sd_setImage(
with: card.imageURL,
placeholderImage: isCompact ? newsIcon : photoIcon
) { [weak imageView] image, _, _, _ in
placeholderImage: icon(for: card.layout)
) { [weak self] image, _, _, _ in
if image != nil {
imageView?.contentMode = .scaleAspectFill
self.containerStackView.setNeedsLayout()
self.containerStackView.layoutIfNeeded()
}
self?.imageView.contentMode = .scaleAspectFill
}
NSLayoutConstraint.deactivate(compactImageConstraints + largeImageConstraints)
if isCompact {
containerStackView.alignment = .center
containerStackView.axis = .horizontal
NSLayoutConstraint.activate(compactImageConstraints)
} else {
containerStackView.alignment = .fill
containerStackView.axis = .vertical
NSLayoutConstraint.activate(largeImageConstraints)
self?.containerStackView.setNeedsLayout()
self?.containerStackView.layoutIfNeeded()
}
updateConstraints(for: card.layout)
}
public override func didMoveToWindow() {
@ -150,14 +126,48 @@ public final class StatusCardControl: UIControl {
}
}
private var newsIcon: UIImage? {
UIImage(systemName: "newspaper.fill")
private func updateConstraints(for layout: Layout) {
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)
return UIImage(systemName: "photo", withConfiguration: configuration)
}
}
private func apply(theme: Theme) {
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 {
static let zero = UILayoutPriority(rawValue: 0)
}