Advertisement
Don_Mag

Example Chart - Swift

Jun 8th, 2023 (edited)
1,471
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 7.57 KB | None | 0 0
  1. // example chart view
  2.  
  3. class BarView: UIView {
  4.     var colors: [UIColor] = []
  5.     var values: [CGFloat] = []
  6.     var hConstraints: [NSLayoutConstraint] = []
  7.  
  8.     public func configureBar(maxVal: CGFloat, values: [CGFloat], colors: [UIColor]) {
  9.         guard values.count == colors.count else {
  10.             fatalError("Values count does not match Colors count!")
  11.         }
  12.         subviews.forEach { v in
  13.             v.removeFromSuperview()
  14.         }
  15.         hConstraints = []
  16.         for _ in 0..<values.count {
  17.             let seg = UIView()
  18.             seg.translatesAutoresizingMaskIntoConstraints = false
  19.             addSubview(seg)
  20.             NSLayoutConstraint.activate([
  21.                 seg.leadingAnchor.constraint(equalTo: leadingAnchor),
  22.                 seg.trailingAnchor.constraint(equalTo: trailingAnchor),
  23.                 seg.bottomAnchor.constraint(equalTo: bottomAnchor),
  24.             ])
  25.             hConstraints.append(seg.heightAnchor.constraint(equalToConstant: 0))
  26.         }
  27.         for (seg, c) in zip(subviews, colors) {
  28.             seg.backgroundColor = c
  29.         }
  30.         var curPct: CGFloat = 0
  31.         for (i, v) in values.enumerated() {
  32.             hConstraints[i].isActive = false
  33.             let seg = subviews[i]
  34.             curPct += v
  35.             hConstraints[i] = seg.heightAnchor.constraint(equalTo: heightAnchor, multiplier: curPct)
  36.             hConstraints[i].isActive = true
  37.         }
  38.         subviews.reversed().forEach { v in
  39.             addSubview(v)
  40.         }
  41.     }
  42.     override init(frame: CGRect) {
  43.         super.init(frame: frame)
  44.         commonInit()
  45.     }
  46.     required init?(coder aDecoder: NSCoder) {
  47.         super.init(coder: aDecoder)
  48.         commonInit()
  49.     }
  50.     private func commonInit() {
  51.         layer.cornerRadius = 12
  52.         clipsToBounds = true
  53.     }
  54.    
  55. }
  56. class LegendDotView: UIView {
  57.     override func layoutSubviews() {
  58.         super.layoutSubviews()
  59.         layer.cornerRadius = bounds.width * 0.5
  60.     }
  61. }
  62. class StarterChartView: UIView {
  63.     var colors: [UIColor] = [.systemRed, .systemYellow, .systemGreen]
  64.     var values: [[CGFloat]] = []
  65.    
  66.     let barsStackView = UIStackView()
  67.     var barTopLabels: [UILabel] = []
  68.    
  69.     override init(frame: CGRect) {
  70.         super.init(frame: frame)
  71.         commonInit()
  72.     }
  73.     required init?(coder aDecoder: NSCoder) {
  74.         super.init(coder: aDecoder)
  75.         commonInit()
  76.     }
  77.     private func commonInit() {
  78.         backgroundColor = .black
  79.        
  80.         let stackView = UIStackView()
  81.         stackView.axis = .vertical
  82.         stackView.distribution = .equalCentering
  83.         stackView.translatesAutoresizingMaskIntoConstraints = false
  84.         addSubview(stackView)
  85.         NSLayoutConstraint.activate([
  86.             stackView.topAnchor.constraint(equalTo: topAnchor, constant: 40.0),
  87.             stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
  88.             stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -72.0),
  89.             stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -60.0),
  90.         ])
  91.        
  92.         [120, 80, 40, 0].forEach { val in
  93.             let hLine = UIView()
  94.             hLine.backgroundColor = .gray
  95.             hLine.heightAnchor.constraint(equalToConstant: 1.0).isActive = true
  96.             stackView.addArrangedSubview(hLine)
  97.             let label = UILabel()
  98.             label.textColor = .lightGray
  99.             label.textAlignment = .center
  100.             label.text = "\(val) h"
  101.             label.translatesAutoresizingMaskIntoConstraints = false
  102.             addSubview(label)
  103.             NSLayoutConstraint.activate([
  104.                 label.leadingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: 8.0),
  105.                 label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8.0),
  106.                 label.centerYAnchor.constraint(equalTo: hLine.centerYAnchor),
  107.             ])
  108.         }
  109.        
  110.         let legendStackView = UIStackView()
  111.         legendStackView.alignment = .center
  112.         legendStackView.spacing = 8
  113.         let legs: [String] = ["Work", "Housework", "Kids"]
  114.         for (s, c) in zip(legs, colors) {
  115.             let dot = LegendDotView()
  116.             dot.backgroundColor = c
  117.             dot.heightAnchor.constraint(equalToConstant: 10.0).isActive = true
  118.             dot.widthAnchor.constraint(equalTo: dot.heightAnchor, multiplier: 1.0).isActive = true
  119.             let label = UILabel()
  120.             label.textColor = .lightGray
  121.             label.text = s
  122.             legendStackView.addArrangedSubview(dot)
  123.             legendStackView.addArrangedSubview(label)
  124.         }
  125.         legendStackView.translatesAutoresizingMaskIntoConstraints = false
  126.         addSubview(legendStackView)
  127.         NSLayoutConstraint.activate([
  128.             legendStackView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
  129.             legendStackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8.0)
  130.         ])
  131.        
  132.         barsStackView.spacing = 40.0
  133.         barsStackView.alignment = .bottom
  134.         barsStackView.translatesAutoresizingMaskIntoConstraints = false
  135.         addSubview(barsStackView)
  136.         NSLayoutConstraint.activate([
  137.             barsStackView.topAnchor.constraint(equalTo: stackView.topAnchor, constant: 0.0),
  138.             barsStackView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0.0),
  139.             barsStackView.centerXAnchor.constraint(equalTo: stackView.centerXAnchor),
  140.         ])
  141.     }
  142.  
  143.    
  144.     func configureChart(maxVal: CGFloat, values: [[CGFloat]]) {
  145.         barTopLabels.forEach { v in
  146.             v.removeFromSuperview()
  147.         }
  148.         barTopLabels = []
  149.         barsStackView.arrangedSubviews.forEach { v in
  150.             v.removeFromSuperview()
  151.         }
  152.        
  153.         var pctVals: [[CGFloat]] = []
  154.         values.forEach { valSet in
  155.             let total = valSet.reduce(0, +)
  156.             let pv = valSet.compactMap({ $0 / total})
  157.             pctVals.append(pv)
  158.         }
  159.        
  160.         for (hValSet, pValSet) in zip(values, pctVals) {
  161.             let b = BarView()
  162.             b.configureBar(maxVal: maxVal, values: pValSet, colors: colors)
  163.             barsStackView.addArrangedSubview(b)
  164.             b.widthAnchor.constraint(equalToConstant: 80.0).isActive = true
  165.             let total = hValSet.reduce(0, +)
  166.             let barPct = total / maxVal
  167.             b.heightAnchor.constraint(equalTo: barsStackView.heightAnchor, multiplier: barPct).isActive = true
  168.             let label = UILabel()
  169.             label.textAlignment = .center
  170.             label.textColor = .white
  171.             let mx = hValSet.reduce(0.0, +)
  172.             label.text = "\(Int(mx)) h"
  173.             label.translatesAutoresizingMaskIntoConstraints = false
  174.             addSubview(label)
  175.             label.bottomAnchor.constraint(equalTo: b.topAnchor, constant: -8.0).isActive = true
  176.             label.centerXAnchor.constraint(equalTo: b.centerXAnchor).isActive = true
  177.             barTopLabels.append(label)
  178.         }
  179.     }
  180.  
  181. }
  182.  
  183. class StarterChartVC: UIViewController {
  184.    
  185.     let sampleChartView = StarterChartView()
  186.    
  187.     var sampleValueSets: [[[CGFloat]]] = [
  188.         [[40, 40, 40], [55, 10, 30]],
  189.         [[60, 40, 20], [40, 5, 20]],
  190.         [[50, 30, 20], [50, 15, 10]],
  191.         [[30, 40, 20], [50, 35, 30]],
  192.     ]
  193.    
  194.     let infolabel = UILabel()
  195.  
  196.     override func viewDidLoad() {
  197.         super.viewDidLoad()
  198.         view.backgroundColor = .systemBackground
  199.        
  200.         sampleChartView.translatesAutoresizingMaskIntoConstraints = false
  201.         view.addSubview(sampleChartView)
  202.        
  203.         let g = view.safeAreaLayoutGuide
  204.         NSLayoutConstraint.activate([
  205.             sampleChartView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
  206.             sampleChartView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
  207.             sampleChartView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
  208.             sampleChartView.heightAnchor.constraint(equalTo: sampleChartView.widthAnchor, multiplier: 1.0),
  209.         ])
  210.  
  211.         infolabel.numberOfLines = 0
  212.         infolabel.textAlignment = .center
  213.         infolabel.translatesAutoresizingMaskIntoConstraints = false
  214.         view.addSubview(infolabel)
  215.         NSLayoutConstraint.activate([
  216.             infolabel.topAnchor.constraint(equalTo: sampleChartView.bottomAnchor, constant: 40.0),
  217.             infolabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
  218.         ])
  219.  
  220.         updateValues()
  221.     }
  222.     override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  223.         updateValues()
  224.     }
  225.     func updateValues() {
  226.         let theseVals = sampleValueSets.removeFirst()
  227.         sampleChartView.configureChart(maxVal: 120, values: theseVals)
  228.         sampleValueSets.append(theseVals)
  229.         infolabel.text = "Tap anywhere to cycle through\na few sample value sets...\n\n" + theseVals.description
  230.     }
  231. }
  232.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement