93 lines
2.6 KiB
Swift
93 lines
2.6 KiB
Swift
|
|
//
|
||
|
|
// StackView.swift
|
||
|
|
// App
|
||
|
|
//
|
||
|
|
// Created by James Magahern on 9/22/20.
|
||
|
|
//
|
||
|
|
|
||
|
|
import UIKit
|
||
|
|
|
||
|
|
class StackView: UIView
|
||
|
|
{
|
||
|
|
var arrangedSubviews: [UIView] = []
|
||
|
|
{ didSet { setNeedsLayout() } }
|
||
|
|
|
||
|
|
var layoutDimension: UIAxis = .vertical
|
||
|
|
|
||
|
|
convenience init(dimension: UIAxis) {
|
||
|
|
self.init(frame: .zero)
|
||
|
|
self.layoutDimension = dimension
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convenience
|
||
|
|
public func addArrangedSubview(_ view: UIView) {
|
||
|
|
addSubview(view)
|
||
|
|
arrangedSubviews.append(view)
|
||
|
|
setNeedsLayout()
|
||
|
|
}
|
||
|
|
|
||
|
|
public func removeArrangedSubview(_ view: UIView) {
|
||
|
|
if view.superview == self {
|
||
|
|
view.removeFromSuperview()
|
||
|
|
}
|
||
|
|
|
||
|
|
arrangedSubviews.removeAll { $0 == view }
|
||
|
|
setNeedsLayout()
|
||
|
|
}
|
||
|
|
|
||
|
|
public func removeAllArrangedSubviews() {
|
||
|
|
arrangedSubviews.forEach { $0.removeFromSuperview() }
|
||
|
|
arrangedSubviews.removeAll()
|
||
|
|
setNeedsLayout()
|
||
|
|
}
|
||
|
|
|
||
|
|
override func sizeThatFits(_ containerSize: CGSize) -> CGSize {
|
||
|
|
var size: CGSize = .zero
|
||
|
|
|
||
|
|
if layoutDimension == .horizontal {
|
||
|
|
size.height = containerSize.height
|
||
|
|
} else {
|
||
|
|
size.width = containerSize.width
|
||
|
|
}
|
||
|
|
|
||
|
|
var spaceRemaining = containerSize
|
||
|
|
for view in arrangedSubviews {
|
||
|
|
let viewSize = view.sizeThatFits(spaceRemaining)
|
||
|
|
if layoutDimension == .horizontal {
|
||
|
|
size.width += viewSize.width
|
||
|
|
spaceRemaining.width -= viewSize.width
|
||
|
|
} else {
|
||
|
|
size.height += viewSize.height
|
||
|
|
spaceRemaining.height -= viewSize.height
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return size
|
||
|
|
}
|
||
|
|
|
||
|
|
override func layoutSubviews() {
|
||
|
|
super.layoutSubviews()
|
||
|
|
|
||
|
|
var origin: CGPoint = CGPoint(x: safeAreaInsets.left, y: safeAreaInsets.top)
|
||
|
|
var spaceRemaining = bounds.size
|
||
|
|
for view in arrangedSubviews {
|
||
|
|
var viewSize = view.sizeThatFits(spaceRemaining)
|
||
|
|
|
||
|
|
var offset: CGPoint = .zero
|
||
|
|
if layoutDimension == .horizontal {
|
||
|
|
offset.x = viewSize.width
|
||
|
|
viewSize.height = bounds.height
|
||
|
|
spaceRemaining.width -= viewSize.width
|
||
|
|
} else {
|
||
|
|
offset.y = viewSize.height
|
||
|
|
viewSize.width = bounds.width
|
||
|
|
spaceRemaining.height -= viewSize.height
|
||
|
|
}
|
||
|
|
|
||
|
|
view.frame = CGRect(origin: origin, size: viewSize)
|
||
|
|
origin.x += offset.x
|
||
|
|
origin.y += offset.y
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|