Skip to content

Instantly share code, notes, and snippets.

@uvolchyk
Created January 30, 2021 21:53
Show Gist options
  • Save uvolchyk/ebbe45c971f4cdc8e024717ac94b7241 to your computer and use it in GitHub Desktop.
Save uvolchyk/ebbe45c971f4cdc8e024717ac94b7241 to your computer and use it in GitHub Desktop.
import UIKit
let kPadding: CGFloat = 20
let kAnimationDuration: TimeInterval = 0.3
let kAnimationDelay: TimeInterval = 0
let kTextSpacing: CGFloat = 10
let kFondSize: CGFloat = 20
class MagicCell: UITableViewCell {
var model: ViewData!
var expandCallback: ((() -> ()) -> ())!
lazy var mainStack: UIStackView = {
let view = UIStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .vertical
view.spacing = kTextSpacing
view.addArrangedSubview(self.summaryLabel)
view.addArrangedSubview(self.additionalStack)
return view
}()
lazy var additionalStack: UIStackView = {
let view = UIStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .horizontal
view.distribution = .equalCentering
view.addArrangedSubview(self.dateLabel)
view.addArrangedSubview(self.expandButton)
return view
}()
lazy var titleLabel: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.font = .systemFont(ofSize: kFondSize, weight: .bold)
view.numberOfLines = .zero
view.lineBreakMode = .byWordWrapping
return view
}()
lazy var summaryLabel: UILabel = {
let view = UILabel()
view.numberOfLines = .zero
view.lineBreakMode = .byWordWrapping
return view
}()
lazy var dateLabel: UILabel = {
let view = UILabel()
view.textColor = .darkGray
return view
}()
lazy var expandButton: UIButton = {
let view = UIButton()
view.setImage(UIImage(systemName: "ellipsis"), for: .normal)
view.addTarget(self, action: #selector(expandButtonTap), for: .touchUpInside)
return view
}()
// MARK: - Init
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("Not implemented 🙃")
}
// MARK: - Layout
override func layoutIfNeeded() {
super.layoutIfNeeded()
NSLayoutConstraint.activate([
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: kPadding),
titleLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: kPadding),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -kPadding),
titleLabel.bottomAnchor.constraint(lessThanOrEqualTo: mainStack.topAnchor, constant: -kPadding),
mainStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: kPadding),
mainStack.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: kPadding),
mainStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -kPadding),
mainStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -kPadding)
])
}
private func setupViews() {
contentView.addSubview(mainStack)
contentView.addSubview(titleLabel)
}
// MARK: -
func configureWithData(_ data: ViewData, completion: @escaping (() -> ()) -> ()) {
model = data
expandCallback = completion
titleLabel.text = data.title
summaryLabel.text = data.summary
summaryLabel.isHidden = !data.expanded
dateLabel.text = data.date
}
@objc func expandButtonTap() {
expandCallback({ [unowned self] in
self.model.expanded.toggle()
let titleHeight = self.titleLabel.frame.height
UIView.animateKeyframes(withDuration: kAnimationDuration,
delay: kAnimationDelay,
options: .calculationModeLinear) {
self.titleLabel.heightAnchor.constraint(equalToConstant: titleHeight).isActive = true
self.summaryLabel.isHidden = !self.model.expanded
} completion: { (finished) in
self.titleLabel.heightAnchor.constraint(equalToConstant: titleHeight).isActive = false
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment