Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // example chart view
- class BarView: UIView {
- var colors: [UIColor] = []
- var values: [CGFloat] = []
- var hConstraints: [NSLayoutConstraint] = []
- public func configureBar(maxVal: CGFloat, values: [CGFloat], colors: [UIColor]) {
- guard values.count == colors.count else {
- fatalError("Values count does not match Colors count!")
- }
- subviews.forEach { v in
- v.removeFromSuperview()
- }
- hConstraints = []
- for _ in 0..<values.count {
- let seg = UIView()
- seg.translatesAutoresizingMaskIntoConstraints = false
- addSubview(seg)
- NSLayoutConstraint.activate([
- seg.leadingAnchor.constraint(equalTo: leadingAnchor),
- seg.trailingAnchor.constraint(equalTo: trailingAnchor),
- seg.bottomAnchor.constraint(equalTo: bottomAnchor),
- ])
- hConstraints.append(seg.heightAnchor.constraint(equalToConstant: 0))
- }
- for (seg, c) in zip(subviews, colors) {
- seg.backgroundColor = c
- }
- var curPct: CGFloat = 0
- for (i, v) in values.enumerated() {
- hConstraints[i].isActive = false
- let seg = subviews[i]
- curPct += v
- hConstraints[i] = seg.heightAnchor.constraint(equalTo: heightAnchor, multiplier: curPct)
- hConstraints[i].isActive = true
- }
- subviews.reversed().forEach { v in
- addSubview(v)
- }
- }
- override init(frame: CGRect) {
- super.init(frame: frame)
- commonInit()
- }
- required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- commonInit()
- }
- private func commonInit() {
- layer.cornerRadius = 12
- clipsToBounds = true
- }
- }
- class LegendDotView: UIView {
- override func layoutSubviews() {
- super.layoutSubviews()
- layer.cornerRadius = bounds.width * 0.5
- }
- }
- class StarterChartView: UIView {
- var colors: [UIColor] = [.systemRed, .systemYellow, .systemGreen]
- var values: [[CGFloat]] = []
- let barsStackView = UIStackView()
- var barTopLabels: [UILabel] = []
- override init(frame: CGRect) {
- super.init(frame: frame)
- commonInit()
- }
- required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- commonInit()
- }
- private func commonInit() {
- backgroundColor = .black
- let stackView = UIStackView()
- stackView.axis = .vertical
- stackView.distribution = .equalCentering
- stackView.translatesAutoresizingMaskIntoConstraints = false
- addSubview(stackView)
- NSLayoutConstraint.activate([
- stackView.topAnchor.constraint(equalTo: topAnchor, constant: 40.0),
- stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
- stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -72.0),
- stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -60.0),
- ])
- [120, 80, 40, 0].forEach { val in
- let hLine = UIView()
- hLine.backgroundColor = .gray
- hLine.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
- stackView.addArrangedSubview(hLine)
- let label = UILabel()
- label.textColor = .lightGray
- label.textAlignment = .center
- label.text = "\(val) h"
- label.translatesAutoresizingMaskIntoConstraints = false
- addSubview(label)
- NSLayoutConstraint.activate([
- label.leadingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: 8.0),
- label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8.0),
- label.centerYAnchor.constraint(equalTo: hLine.centerYAnchor),
- ])
- }
- let legendStackView = UIStackView()
- legendStackView.alignment = .center
- legendStackView.spacing = 8
- let legs: [String] = ["Work", "Housework", "Kids"]
- for (s, c) in zip(legs, colors) {
- let dot = LegendDotView()
- dot.backgroundColor = c
- dot.heightAnchor.constraint(equalToConstant: 10.0).isActive = true
- dot.widthAnchor.constraint(equalTo: dot.heightAnchor, multiplier: 1.0).isActive = true
- let label = UILabel()
- label.textColor = .lightGray
- label.text = s
- legendStackView.addArrangedSubview(dot)
- legendStackView.addArrangedSubview(label)
- }
- legendStackView.translatesAutoresizingMaskIntoConstraints = false
- addSubview(legendStackView)
- NSLayoutConstraint.activate([
- legendStackView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
- legendStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0)
- ])
- barsStackView.spacing = 40.0
- barsStackView.alignment = .bottom
- barsStackView.translatesAutoresizingMaskIntoConstraints = false
- addSubview(barsStackView)
- NSLayoutConstraint.activate([
- barsStackView.topAnchor.constraint(equalTo: stackView.topAnchor, constant: 0.0),
- barsStackView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0.0),
- barsStackView.centerXAnchor.constraint(equalTo: stackView.centerXAnchor),
- ])
- }
- func configureChart(maxVal: CGFloat, values: [[CGFloat]]) {
- barTopLabels.forEach { v in
- v.removeFromSuperview()
- }
- barTopLabels = []
- barsStackView.arrangedSubviews.forEach { v in
- v.removeFromSuperview()
- }
- var pctVals: [[CGFloat]] = []
- values.forEach { valSet in
- let total = valSet.reduce(0, +)
- let pv = valSet.compactMap({ $0 / total})
- pctVals.append(pv)
- }
- for (hValSet, pValSet) in zip(values, pctVals) {
- let b = BarView()
- b.configureBar(maxVal: maxVal, values: pValSet, colors: colors)
- barsStackView.addArrangedSubview(b)
- b.widthAnchor.constraint(equalToConstant: 80.0).isActive = true
- let total = hValSet.reduce(0, +)
- let barPct = total / maxVal
- b.heightAnchor.constraint(equalTo: barsStackView.heightAnchor, multiplier: barPct).isActive = true
- let label = UILabel()
- label.textAlignment = .center
- label.textColor = .white
- let mx = hValSet.reduce(0.0, +)
- label.text = "\(Int(mx)) h"
- label.translatesAutoresizingMaskIntoConstraints = false
- addSubview(label)
- label.bottomAnchor.constraint(equalTo: b.topAnchor, constant: -8.0).isActive = true
- label.centerXAnchor.constraint(equalTo: b.centerXAnchor).isActive = true
- barTopLabels.append(label)
- }
- }
- }
- class StarterChartVC: UIViewController {
- let sampleChartView = StarterChartView()
- var sampleValueSets: [[[CGFloat]]] = [
- [[40, 40, 40], [55, 10, 30]],
- [[60, 40, 20], [40, 5, 20]],
- [[50, 30, 20], [50, 15, 10]],
- [[30, 40, 20], [50, 35, 30]],
- ]
- let infolabel = UILabel()
- override func viewDidLoad() {
- super.viewDidLoad()
- view.backgroundColor = .systemBackground
- sampleChartView.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(sampleChartView)
- let g = view.safeAreaLayoutGuide
- NSLayoutConstraint.activate([
- sampleChartView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
- sampleChartView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
- sampleChartView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
- sampleChartView.heightAnchor.constraint(equalTo: sampleChartView.widthAnchor, multiplier: 1.0),
- ])
- infolabel.numberOfLines = 0
- infolabel.textAlignment = .center
- infolabel.translatesAutoresizingMaskIntoConstraints = false
- view.addSubview(infolabel)
- NSLayoutConstraint.activate([
- infolabel.topAnchor.constraint(equalTo: sampleChartView.bottomAnchor, constant: 40.0),
- infolabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
- ])
- updateValues()
- }
- override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
- updateValues()
- }
- func updateValues() {
- let theseVals = sampleValueSets.removeFirst()
- sampleChartView.configureChart(maxVal: 120, values: theseVals)
- sampleValueSets.append(theseVals)
- infolabel.text = "Tap anywhere to cycle through\na few sample value sets...\n\n" + theseVals.description
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement