chore: use stackView

This commit is contained in:
sunxiaojian 2021-04-16 21:55:09 +08:00
parent ca7eb7bb12
commit cfdd2ea670
6 changed files with 176 additions and 74 deletions

View File

@ -136,6 +136,7 @@
5D0393902612D259007FE196 /* WebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D03938F2612D259007FE196 /* WebViewController.swift */; };
5D0393962612D266007FE196 /* WebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0393952612D266007FE196 /* WebViewModel.swift */; };
5D526FE225BE9AC400460CB9 /* MastodonSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 5D526FE125BE9AC400460CB9 /* MastodonSDK */; };
5DA732CC2629CEF500A92342 /* UIView+Remove.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA732CB2629CEF500A92342 /* UIView+Remove.swift */; };
5DDDF1932617442700311060 /* Mastodon+Entity+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DDDF1922617442700311060 /* Mastodon+Entity+Account.swift */; };
5DDDF1992617447F00311060 /* Mastodon+Entity+Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DDDF1982617447F00311060 /* Mastodon+Entity+Tag.swift */; };
5DDDF1A92617489F00311060 /* Mastodon+Entity+History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DDDF1A82617489F00311060 /* Mastodon+Entity+History.swift */; };
@ -525,6 +526,7 @@
459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; };
5D03938F2612D259007FE196 /* WebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewController.swift; sourceTree = "<group>"; };
5D0393952612D266007FE196 /* WebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewModel.swift; sourceTree = "<group>"; };
5DA732CB2629CEF500A92342 /* UIView+Remove.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Remove.swift"; sourceTree = "<group>"; };
5DDDF1922617442700311060 /* Mastodon+Entity+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Account.swift"; sourceTree = "<group>"; };
5DDDF1982617447F00311060 /* Mastodon+Entity+Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+Tag.swift"; sourceTree = "<group>"; };
5DDDF1A82617489F00311060 /* Mastodon+Entity+History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Mastodon+Entity+History.swift"; sourceTree = "<group>"; };
@ -1614,6 +1616,7 @@
5DF1056325F887CB00D6C0D4 /* AVPlayer.swift */,
DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */,
2D32EAB925CB9B0500C9ED86 /* UIView.swift */,
5DA732CB2629CEF500A92342 /* UIView+Remove.swift */,
2DFF41882614A4DC00F776A4 /* UIView+Constraint.swift */,
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */,
2D24E1222626ED9D00A59D4F /* UIView+Gesture.swift */,
@ -2329,6 +2332,7 @@
DB71FD3C25F8A1C500512AE1 /* APIService+Persist+PersistCache.swift in Sources */,
2DA6055125F74407006356F9 /* AudioContainerViewModel.swift in Sources */,
0FB3D2FE25E4CB6400AAD544 /* PickServerTitleCell.swift in Sources */,
5DA732CC2629CEF500A92342 /* UIView+Remove.swift in Sources */,
2D38F1DF25CD46A400561493 /* HomeTimelineViewController+StatusProvider.swift in Sources */,
2D206B9225F60EA700143C56 /* UIControl.swift in Sources */,
2D46975E25C2A54100CF4AA9 /* NSLayoutConstraint.swift in Sources */,

View File

@ -0,0 +1,18 @@
//
// UIView+Remove.swift
// Mastodon
//
// Created by xiaojian sun on 2021/4/16.
//
import Foundation
import UIKit
extension UIView {
func removeFromStackView() {
if let stackView = self.superview as? UIStackView {
stackView.removeArrangedSubview(self)
}
self.removeFromSuperview()
}
}

View File

@ -35,7 +35,7 @@ final class NotificationViewController: UIViewController, NeedsDependency {
tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self))
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
tableView.tableFooterView = UIView()
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
return tableView
}()

View File

@ -74,9 +74,7 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
newSnapshot.appendItems([.bottomLoader], toSection: .main)
}
guard let difference = self.calculateReloadSnapshotDifference(navigationBar: navigationBar, tableView: tableView, oldSnapshot: oldSnapshot, newSnapshot: newSnapshot) else {
diffableDataSource.apply(newSnapshot, animatingDifferences: false) {
tableView.reloadData()
}
diffableDataSource.apply(newSnapshot, animatingDifferences: false)
self.isFetchingLatestNotification.value = false
return
}

View File

@ -11,7 +11,6 @@ import UIKit
final class NotificationStatusTableViewCell: UITableViewCell {
static let actionImageBorderWidth: CGFloat = 2
static let statusPadding = UIEdgeInsets(top: 50, left: 73, bottom: 24, right: 24)
var disposeBag = Set<AnyCancellable>()
var pollCountdownSubscription: AnyCancellable?
@ -42,6 +41,11 @@ final class NotificationStatusTableViewCell: UITableViewCell {
return view
}()
let avatarContainer: UIView = {
let view = UIView()
return view
}()
let actionLabel: UILabel = {
let label = UILabel()
label.textColor = Asset.Colors.Label.secondary.color
@ -103,53 +107,99 @@ final class NotificationStatusTableViewCell: UITableViewCell {
extension NotificationStatusTableViewCell {
func configure() {
let container = UIView()
container.backgroundColor = .clear
contentView.addSubview(container)
container.constrain([
container.topAnchor.constraint(equalTo: contentView.topAnchor),
container.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
container.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor),
container.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
let containerStackView = UIStackView()
containerStackView.axis = .horizontal
containerStackView.alignment = .top
containerStackView.spacing = 4
containerStackView.layoutMargins = UIEdgeInsets(top: 14, left: 0, bottom: 12, right: 0)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
contentView.readableContentGuide.trailingAnchor.constraint(equalTo: containerStackView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor),
])
container.addSubview(avatatImageView)
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
avatatImageView.pin(top: 12, left: 0, bottom: nil, right: nil)
container.addSubview(actionImageBackground)
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
actionImageBackground.pin(top: 33, left: 21, bottom: nil, right: nil)
actionImageBackground.addSubview(actionImageView)
actionImageView.constrainToCenter()
container.addSubview(nameLabel)
nameLabel.constrain([
nameLabel.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
nameLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 61)
containerStackView.addArrangedSubview(avatarContainer)
avatarContainer.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
avatarContainer.heightAnchor.constraint(equalToConstant: 47).priority(.required - 1),
avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1)
])
avatarContainer.addSubview(avatatImageView)
avatatImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
avatatImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
avatatImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
])
avatarContainer.addSubview(actionImageBackground)
actionImageBackground.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
actionImageBackground.heightAnchor.constraint(equalToConstant: 24 + NotificationTableViewCell.actionImageBorderWidth).priority(.required - 1),
actionImageBackground.widthAnchor.constraint(equalToConstant: 24 + NotificationTableViewCell.actionImageBorderWidth).priority(.required - 1),
actionImageBackground.bottomAnchor.constraint(equalTo: avatarContainer.bottomAnchor),
actionImageBackground.trailingAnchor.constraint(equalTo: avatarContainer.trailingAnchor)
])
avatarContainer.addSubview(actionImageView)
actionImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
actionImageView.centerXAnchor.constraint(equalTo: actionImageBackground.centerXAnchor),
actionImageView.centerYAnchor.constraint(equalTo: actionImageBackground.centerYAnchor)
])
let actionStackView = UIStackView()
actionStackView.axis = .horizontal
actionStackView.distribution = .fillProportionally
actionStackView.spacing = 4
actionStackView.translatesAutoresizingMaskIntoConstraints = false
nameLabel.translatesAutoresizingMaskIntoConstraints = false
actionStackView.addArrangedSubview(nameLabel)
actionLabel.translatesAutoresizingMaskIntoConstraints = false
actionStackView.addArrangedSubview(actionLabel)
nameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
let statusStackView = UIStackView()
statusStackView.axis = .vertical
statusStackView.distribution = .fill
statusStackView.spacing = 4
statusStackView.translatesAutoresizingMaskIntoConstraints = false
statusView.translatesAutoresizingMaskIntoConstraints = false
statusStackView.addArrangedSubview(actionStackView)
statusBorder.translatesAutoresizingMaskIntoConstraints = false
statusView.translatesAutoresizingMaskIntoConstraints = false
statusBorder.addSubview(statusView)
NSLayoutConstraint.activate([
statusView.topAnchor.constraint(equalTo: statusBorder.topAnchor, constant: 12),
statusView.leadingAnchor.constraint(equalTo: statusBorder.leadingAnchor, constant: 12),
statusBorder.bottomAnchor.constraint(equalTo: statusView.bottomAnchor, constant: 12),
statusBorder.trailingAnchor.constraint(equalTo: statusView.trailingAnchor, constant: 12),
])
container.addSubview(actionLabel)
actionLabel.constrain([
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4)
])
statusStackView.addArrangedSubview(statusBorder)
containerStackView.addArrangedSubview(statusStackView)
statusView.contentWarningBlurContentImageView.backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color
statusView.isUserInteractionEnabled = false
// remove item don't display
statusView.actionToolbarContainer.isHidden = true
statusView.avatarView.isHidden = true
statusView.usernameLabel.isHidden = true
container.addSubview(statusBorder)
statusBorder.pin(top: 40, left: 63, bottom: 14, right: 14)
container.addSubview(statusView)
statusView.pin(top: NotificationStatusTableViewCell.statusPadding.top, left: NotificationStatusTableViewCell.statusPadding.left, bottom: NotificationStatusTableViewCell.statusPadding.bottom, right: NotificationStatusTableViewCell.statusPadding.right)
statusView.actionToolbarContainer.removeFromStackView()
// it affect stackView's height
statusView.avatarView.removeFromStackView()
statusView.usernameLabel.removeFromStackView()
statusView.nameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
statusView.activeTextLabel.setContentCompressionResistancePriority(.required, for: .vertical)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {

View File

@ -50,6 +50,11 @@ final class NotificationTableViewCell: UITableViewCell {
return view
}()
let avatarContainer: UIView = {
let view = UIView()
return view
}()
let actionLabel: UILabel = {
let label = UILabel()
label.textColor = Asset.Colors.Label.secondary.color
@ -86,40 +91,67 @@ final class NotificationTableViewCell: UITableViewCell {
extension NotificationTableViewCell {
func configure() {
let container = UIView()
container.backgroundColor = .clear
contentView.addSubview(container)
container.constrain([
container.topAnchor.constraint(equalTo: contentView.topAnchor),
container.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
container.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor),
container.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
let containerStackView = UIStackView()
containerStackView.axis = .horizontal
containerStackView.alignment = .center
containerStackView.spacing = 4
containerStackView.layoutMargins = UIEdgeInsets(top: 14, left: 0, bottom: 12, right: 0)
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor),
containerStackView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
contentView.readableContentGuide.trailingAnchor.constraint(equalTo: containerStackView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor),
])
container.addSubview(avatatImageView)
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
avatatImageView.pin(top: 12, left: 0, bottom: nil, right: nil)
container.addSubview(actionImageBackground)
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
actionImageBackground.pin(top: 33, left: 33, bottom: nil, right: nil)
actionImageBackground.addSubview(actionImageView)
actionImageView.constrainToCenter()
container.addSubview(nameLabel)
nameLabel.constrain([
nameLabel.topAnchor.constraint(equalTo: container.topAnchor, constant: 24),
container.bottomAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 24),
nameLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 61)
containerStackView.addArrangedSubview(avatarContainer)
avatarContainer.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
avatarContainer.heightAnchor.constraint(equalToConstant: 47).priority(.required - 1),
avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1)
])
avatarContainer.addSubview(avatatImageView)
avatatImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
avatatImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
avatatImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
avatatImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
])
avatarContainer.addSubview(actionImageBackground)
actionImageBackground.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
actionImageBackground.heightAnchor.constraint(equalToConstant: 24 + NotificationTableViewCell.actionImageBorderWidth).priority(.required - 1),
actionImageBackground.widthAnchor.constraint(equalToConstant: 24 + NotificationTableViewCell.actionImageBorderWidth).priority(.required - 1),
actionImageBackground.bottomAnchor.constraint(equalTo: avatarContainer.bottomAnchor),
actionImageBackground.trailingAnchor.constraint(equalTo: avatarContainer.trailingAnchor)
])
avatarContainer.addSubview(actionImageView)
actionImageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
actionImageView.centerXAnchor.constraint(equalTo: actionImageBackground.centerXAnchor),
actionImageView.centerYAnchor.constraint(equalTo: actionImageBackground.centerYAnchor)
])
let actionStackView = UIStackView()
actionStackView.axis = .horizontal
actionStackView.distribution = .fillProportionally
actionStackView.spacing = 4
actionStackView.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(actionLabel)
actionLabel.constrain([
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4)
])
nameLabel.translatesAutoresizingMaskIntoConstraints = false
containerStackView.addArrangedSubview(nameLabel)
actionLabel.translatesAutoresizingMaskIntoConstraints = false
containerStackView.addArrangedSubview(actionLabel)
nameLabel.setContentCompressionResistancePriority(.required - 1, for: .vertical)
containerStackView.addArrangedSubview(actionStackView)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {