forked from shadowfacts/Tusker
Make StatusContentContainer play nice with hiding subviews
This commit is contained in:
parent
7085ac01cb
commit
2196663d94
|
@ -30,48 +30,84 @@ class StatusContentContainer: UIView {
|
||||||
|
|
||||||
let pollView = StatusPollView()
|
let pollView = StatusPollView()
|
||||||
|
|
||||||
private var lastSubviewBottomConstraint: NSLayoutConstraint!
|
private var arrangedSubviews: [UIView] {
|
||||||
|
[contentTextView, cardView, attachmentsView, pollView]
|
||||||
|
}
|
||||||
|
|
||||||
|
private var isHiddenObservations: [NSKeyValueObservation] = []
|
||||||
|
|
||||||
|
private var verticalConstraints: [NSLayoutConstraint] = []
|
||||||
|
private var lastSubviewBottomConstraint: NSLayoutConstraint?
|
||||||
private var zeroHeightConstraint: NSLayoutConstraint!
|
private var zeroHeightConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
let subviews = [contentTextView, cardView, attachmentsView, pollView]
|
for subview in arrangedSubviews {
|
||||||
for (index, subview) in subviews.enumerated() {
|
|
||||||
subview.translatesAutoresizingMaskIntoConstraints = false
|
subview.translatesAutoresizingMaskIntoConstraints = false
|
||||||
addSubview(subview)
|
addSubview(subview)
|
||||||
|
|
||||||
let topConstraint: NSLayoutConstraint
|
|
||||||
if index == 0 {
|
|
||||||
topConstraint = subview.topAnchor.constraint(equalTo: topAnchor)
|
|
||||||
} else {
|
|
||||||
topConstraint = subview.topAnchor.constraint(equalTo: subviews[index - 1].bottomAnchor, constant: 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
topConstraint,
|
|
||||||
subview.leadingAnchor.constraint(equalTo: leadingAnchor),
|
subview.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
subview.trailingAnchor.constraint(equalTo: trailingAnchor),
|
subview.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
// these constraints need to have low priority so that during the collapse/expand animation, the content container is the view that shrinks/expands
|
// this constraint needs to have low priority so that during the collapse/expand animation, the content container is the view that shrinks/expands
|
||||||
lastSubviewBottomConstraint = subviews.last!.bottomAnchor.constraint(equalTo: bottomAnchor)
|
|
||||||
lastSubviewBottomConstraint.isActive = true
|
|
||||||
lastSubviewBottomConstraint.priority = .defaultLow
|
|
||||||
zeroHeightConstraint = heightAnchor.constraint(equalToConstant: 0)
|
zeroHeightConstraint = heightAnchor.constraint(equalToConstant: 0)
|
||||||
zeroHeightConstraint.priority = .defaultLow
|
zeroHeightConstraint.priority = .defaultLow
|
||||||
|
|
||||||
|
setNeedsUpdateConstraints()
|
||||||
|
|
||||||
// mask to bounds so that the during the expand/collapse animation, subviews are clipped
|
// mask to bounds so that the during the expand/collapse animation, subviews are clipped
|
||||||
layer.masksToBounds = true
|
layer.masksToBounds = true
|
||||||
|
|
||||||
|
isHiddenObservations = arrangedSubviews.map {
|
||||||
|
$0.observe(\.isHidden) { [unowned self] _, _ in
|
||||||
|
self.setNeedsUpdateConstraints()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func updateConstraints() {
|
||||||
|
NSLayoutConstraint.deactivate(verticalConstraints)
|
||||||
|
verticalConstraints = []
|
||||||
|
var lastVisibleSubview: UIView?
|
||||||
|
|
||||||
|
for subview in arrangedSubviews {
|
||||||
|
guard !subview.isHidden else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if let lastVisibleSubview {
|
||||||
|
verticalConstraints.append(subview.topAnchor.constraint(equalTo: lastVisibleSubview.bottomAnchor, constant: 4))
|
||||||
|
} else {
|
||||||
|
verticalConstraints.append(subview.topAnchor.constraint(equalTo: topAnchor))
|
||||||
|
}
|
||||||
|
|
||||||
|
lastVisibleSubview = subview
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate(verticalConstraints)
|
||||||
|
|
||||||
|
lastSubviewBottomConstraint?.isActive = false
|
||||||
|
// this constraint needs to have low priority so that during the collapse/expand animation, the content container is the view that shrinks/expands
|
||||||
|
lastSubviewBottomConstraint = subviews.last(where: { !$0.isHidden })!.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||||
|
lastSubviewBottomConstraint!.isActive = true
|
||||||
|
lastSubviewBottomConstraint!.priority = .defaultLow
|
||||||
|
|
||||||
|
super.updateConstraints()
|
||||||
|
}
|
||||||
|
|
||||||
func setCollapsed(_ collapsed: Bool) {
|
func setCollapsed(_ collapsed: Bool) {
|
||||||
lastSubviewBottomConstraint.isActive = !collapsed
|
// ensure that we have a lastSubviewBottomConstraint
|
||||||
|
updateConstraintsIfNeeded()
|
||||||
|
// force unwrap because the content container should always have at least one view
|
||||||
|
lastSubviewBottomConstraint!.isActive = !collapsed
|
||||||
zeroHeightConstraint.isActive = collapsed
|
zeroHeightConstraint.isActive = collapsed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue