Skip to content

collectiveidea/CollectionGraph

Repository files navigation

CollectionGraph Travis CI

A flexible and customizable scatter, bar, and line graphing tool for iOS. Backed by UICollectionViews.

Features

  • Plot numerous collections of data on one graph.
  • Supply custom views for data points, and other elements.
  • Callbacks to customize specific elements.
  • Layout using storyboards (However, IBDesignables do not carry over in linked frameworks)

Installation

Carthage

To integrate CollectionGraph into your Xcode project using Carthage, specify it in your Cartfile:

github "collectiveidea/CollectionGraph"

Usage

  • Check out the CollectionGraphExample target in the project to see some examples

Plotting Points

/////////////// example image //////////////

To plot a graph of simple points, assign the CollectionGraph's graphData property.

import CollectionGraph

var graphData: [[GraphDatum]]?

Each array of [GraphDatum] represents a new "section" in the graph. Each section should represent a different set of data.

For example:

func losAngelesGraphData() -> [GraphhDatum] { ... }
func newYorkGraphData() -> [GraphhDatum] { ... }
func grandRapidsGraphData() -> [GraphhDatum] { ... }

let data = [losAngelesGraphData(), newYorkGraphData(), grandRapidsGraphData()]

Three different sets of points (each city) will be plotted on the same graph.

GraphDatum is a protocol that requires a CGPoint. You can add other properties you may want to surface during the Callbacks to better identify the data.

Example
struct Data: GraphDatum {
    var point: CGPoint
    var id: String
}

Customization

Graph Cells

Custom graphCells

If you want a custom graphCell instead of the default square, you can set the graphCell property.

var graphCell: UICollectionViewCell?

Using the provided Delegate Callbacks, you can set your graphCell properties for specific graphData points

This is great for setting images or labels that change depending on the data.

Gif of Miles Ran

Cell Delegate Callbacks

protocol CollectionGraphCellDelegate: class {

  func collectionGraph(
    cell: UICollectionViewCell,
    forData data: GraphDatum,
    atSection section: Int
    )

  func collectionGraph(
    sizeForGraphCellWithData data: GraphDatum,
    inSection section: Int
    ) -> CGSize
}
  1. Properties Callback - Set the visual treatment on a cell.
    func collectionGraph(cell: UICollectionViewCell, forData data: GraphDatum, atSection section: Int)

Example properties:

  • backgroundColor
  • layer.cornerRadius
  • Any custom properties you added in a subclass
  • etc...
Example usage:
collectionGraph.collectionGraphCellDelegate = self
func collectionGraph(cell: UICollectionViewCell, forData data: GraphDatum, atSection section: Int) {
        cell.backgroundColor = UIColor.darkText
        cell.layer.cornerRadius = cell.frame.width / 2

        // custom graphCell
        if let myCell = cell as? myCell {
          myCell.image = UIImage(named: "donut.png")
        }
    }
  1. Size Callback
func collectionGraph(sizeForGraphCellWithData data: GraphDatum, inSection section: Int) -> CGSize {
    if section == 0 {
        return CGSize(width: 3, height: 3)
    }

    return CGSize(width: 8, height: 8)
}

Bar Graph Views

Used for bar graphs. These are the views that start at the bottom of the graph and extend up to the graphCell. Can be used with line graphs as well.

Custom barViews

If you want a custom barView instead of the default view, you can set the barView property

var barView: UICollectionReusableView?

Gif of bar Graph

BarView Delegate Callbacks

protocol CollectionGraphBarDelegate: class {

    func collectionGraph(
      barView: UICollectionReusableView,
      withData data: GraphDatum,
      inSection section: Int
      )

    func collectionGraph(
      widthForBarViewWithData data: GraphDatum,
      inSection section: Int
      ) -> CGFloat
}
  1. Propery Callback - Set the visual treatment on a bar view.
    func collectionGraph(barView: UICollectionReusableView, withData data: GraphDatum, inSection section: Int)

Example properties:

  • backgroundColor
  • Any custom properties you added in a subclass
  • etc...
Example usage:
collectionGraph.collectionGraphBarDelegate = self
func collectionGraph(barView: UICollectionReusableView, withData data: GraphDatum, inSection section: Int) {
        barView.backgroundColor = UIColor.lightGray
    }

Line Graph Connector Lines

Used for line graphs. These are the lines that connect the graphCells. Can be used with bar graphs as well.

Gif of line Graph

Customizing a Connector Line with Delegate Callbacks

To display connector lines, you need to use the delegate callback and set the line's properties.

protocol CollectionGraphLineDelegate: class {

    func collectionGraph(
      connectorLine: GraphLineShapeLayer,
      withData data: GraphDatum,
      inSection section: Int)
}

The connectorLine property provides a GraphLineShapeLayer which is a subclass of CAShapeLayer, and provides an additional property of straightLines.

class GraphLineShapeLayer: CAShapeLayer {
    public var straightLines: Bool = false
}

You can set all the visual properties of a CAShapeLayer to achieve the look you want.

Example properties:

  • lineWidth
  • straightLines
  • lineDashPattern
  • strokeColor

Example usage:

collectionGraph.collectionGraphLineDelegate = self
func collectionGraph(connectorLine: GraphLineShapeLayer, withData data: GraphDatum, inSection section: Int) {
        connectorLine.lineWidth = 2
        connectorLine.lineDashPattern = [4, 2]
        connectorLine.straightLines = true
        connectorLine.lineCap = kCALineCapRound
        connectorLine.strokeColor = UIColor.darkGray.cgColor
    }

X Labels

To change the text displayed along the X axis, use CollectionGraphLabelsDelegate

public protocol CollectionGraphLabelsDelegate: class {

    func collectionGraph(
      textForXLabelWithCurrentText currentText: String,
      inSection section: Int
      ) -> String
}

Example usage:

collectionGraph.collectionGraphLabelsDelegate = self
func collectionGraph(textForXLabelWithCurrentText currentText: String, inSection section: Int) -> String {
        return ""
    }

Horizontal Y Divider Lines

These are the horizontal lines next to the Y labels that span the length of the graph.

public protocol CollectionGraphYDividerLineDelegate: class {

    func collectionGraph(yDividerLine: CAShapeLayer)
}

Example usage:

collectionGraph.collectionGraphYDividerLineDelegate = self
func collectionGraph(yDividerLine: CAShapeLayer) {
        yDividerLine.lineDashPattern = [1, 8]
        yDividerLine.lineWidth = 2
    }

Settable Properties

Graph width and Insets

Width:
By default the graphCells are plotted within the width of the CollectionGraph.
By setting graphContentWidth you can extend the content width to allow scrolling.

var graphContentWidth: CGFloat

Insets:
Adjust space along the edges of the CollectionGraph.
The left and bottom space is used to layout the labels.

 var topInset: CGFloat

 var leftInset: CGFloat

 var bottomInset: CGFloat

 var rightInset: CGFloat

Side Bar View

A view that lies behind the y axis labels and above the plotted graph. Useful for covering the graph when it scrolls behind the y labels.

var ySideBarView: UICollectionReusableView?

Note! You need to provide a subclass of UICollectionReusableView and override init(frame: CGRect). Inside the init block is where you set your customizations

Initializiing a UICollectionReusableView() and then settings its background color will not work.

Example:

class MySideBarClass: UICollectionReusableView {

  override init(frame: CGRect) {
     super.init(frame: frame)
     backgroundColor = UIColor.red
  }

}

Y Divider Lines

Set the color of the horizontal lines that go across the graph along the Y axis.

var yDividerLineColor: UIColor

Number of labels along the X and Y axes

X:

 var xSteps: Int

Y:

var ySteps: Int

Text for X and Y labels

Color:

var textColor: UIColor

Size:

var textSize: CGFloat

Font Name:

var fontName: String?

Graph Offset

Get and Set the current offset of the CollectionGraph.

var contentOffset: CGPoint

Scroll to a specific data point.

func scrollToDataPoint(
  graphDatum: GraphDatum,
  withAnimation animation: Bool,
  andScrollPosition scrollPosition: UICollectionViewScrollPosition)

Develoment

Install <a href: https://github.com/realm/SwiftLint> SwiftLint for static analysis:

$ brew install swiftlint