A flexible and customizable scatter, bar, and line graphing tool for iOS. Backed by UICollectionViews.
- 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)
To integrate CollectionGraph into your Xcode project using Carthage, specify it in your Cartfile
:
github "collectiveidea/CollectionGraph"
- Check out the CollectionGraphExample target in the project to see some examples
/////////////// 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.
struct Data: GraphDatum {
var point: CGPoint
var id: String
}
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.
protocol CollectionGraphCellDelegate: class {
func collectionGraph(
cell: UICollectionViewCell,
forData data: GraphDatum,
atSection section: Int
)
func collectionGraph(
sizeForGraphCellWithData data: GraphDatum,
inSection section: Int
) -> CGSize
}
- 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...
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")
}
}
- 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)
}
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.
If you want a custom barView instead of the default view, you can set the barView
property
var barView: UICollectionReusableView?
protocol CollectionGraphBarDelegate: class {
func collectionGraph(
barView: UICollectionReusableView,
withData data: GraphDatum,
inSection section: Int
)
func collectionGraph(
widthForBarViewWithData data: GraphDatum,
inSection section: Int
) -> CGFloat
}
- 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...
collectionGraph.collectionGraphBarDelegate = self
func collectionGraph(barView: UICollectionReusableView, withData data: GraphDatum, inSection section: Int) {
barView.backgroundColor = UIColor.lightGray
}
Used for line graphs. These are the lines that connect the graphCells
. Can be used with bar graphs as well.
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
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
}
To change the text displayed along the X axis, use CollectionGraphLabelsDelegate
public protocol CollectionGraphLabelsDelegate: class {
func collectionGraph(
textForXLabelWithCurrentText currentText: String,
inSection section: Int
) -> String
}
collectionGraph.collectionGraphLabelsDelegate = self
func collectionGraph(textForXLabelWithCurrentText currentText: String, inSection section: Int) -> String {
return "•"
}
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)
}
collectionGraph.collectionGraphYDividerLineDelegate = self
func collectionGraph(yDividerLine: CAShapeLayer) {
yDividerLine.lineDashPattern = [1, 8]
yDividerLine.lineWidth = 2
}
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
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.
class MySideBarClass: UICollectionReusableView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.red
}
}
Set the color of the horizontal lines that go across the graph along the Y axis.
var yDividerLineColor: UIColor
X:
var xSteps: Int
Y:
var ySteps: Int
Color:
var textColor: UIColor
Size:
var textSize: CGFloat
Font Name:
var fontName: String?
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)
Install <a href: https://github.com/realm/SwiftLint> SwiftLint for static analysis:
$ brew install swiftlint