An In-Depth look at FlexChart Line Markers in Xuni for iOS
The 2015 v3 release of Xuni brings several major new features to the product, and one of the biggest is interactive line markers for FlexChart. Line markers are a very useful way of conveying a large amount of information to a user in situations where screen real estate is limited, which is often the case in mobile apps. Line markers don’t require the same tapping precision needed to display tooltips, nor do they use up as much screen space as static data labels. Thus they are often the perfect mechanism for allowing a user to interact with a chart, and obtain precise information about multiple series. By simply dragging over the chart a user can quickly determine they information that they need.
Implementing Line Markers
There are two classes that will need to be implemented to use line markers on iOS: one for handling the line marker view and another for intercepting the data points on render. Your first class will inherit from the XuniChartMarkerBaseView class while the second deals with the IXuniChartMarkerRender protocol.
Implementing your own XuniChartMarkerBaseView
First, you’ll want to define you own subclass of XuniChartMarkerBaseView. In your header you’ll define your subclass as well as create a couple of properties to represent your lineMarker and the content of the marker (which in this case is a single label). Also, you’ll want to write your own initWithLineMarker method to initialize your custom line marker when the project runs.
@interface MyMarkerView : XuniChartMarkerBaseView
@property (nonatomic) XuniChartLineMarker *lineMarker;
@property (nonatomic) UILabel *content;
- (id)initWithLineMarker:(XuniChartLineMarker *)lineMarker;
@end
In the implementation file, you’ll need to set up your initWithLineMarker method so that it calls the superclass version of the method, and configures the line marker view. In this example we’re merely adding a label so the configuration is mostly limited to sizing and styling it as well as the containing view.
// Class MyMarkerView
@implementation MyMarkerView
- (id)initWithLineMarker:(XuniChartLineMarker *)lineMarker {
self = [super initWithLineMarker:lineMarker];
if (self) {
_lineMarker = lineMarker;
self.backgroundColor = [UIColor colorWithWhite:0.8 alpha:0.6];
self.frame = CGRectMake(0, 0, 115, 60);
_content = [[UILabel alloc] init];
_content.frame = CGRectMake(5, 5, 105, 50);
_content.backgroundColor = [UIColor clearColor];
_content.font = [UIFont systemFontOfSize:10.0];
[self addSubview:_content];
}
return self;
}
@end
Setting up a custom version of IXuniChartMarkerRender
The next step once again requires adding some code to our header so that we can provide our own XuniChartMarkerRender. We will only provide a single initWithView method in our header.
@interface MyChartMarkerRender : NSObject<IXuniChartMarkerRender>
- (id)initWithView:(XuniChartMarkerBaseView *)view;
@end
Now, we will need to make some additions to the implementation file. First we will specify our initWithView method, and second we will write a renderMarker method which will intercept the data points, format them, and add them to our label.
// Class MyChartMarkerRender
@implementation MyChartMarkerRender {
XuniChartMarkerBaseView *_view;
}
- (id)initWithView:(XuniChartMarkerBaseView *)view {
_view = view;
return self;
}
- (void)renderMarker {
if (_view != nil ) {
MyMarkerView \*view = (MyMarkerView \*)_view;
NSArray *data = view.lineMarker.dataPoints;
if (data != nil && data.count > 0) {
NSString *str = @"";
XuniDataPoint *point = data[0];
str = [str stringByAppendingFormat:@"%@ \\n", point.dataXString];
for (int i = 0; i < data.count - 1; i++) {
point = data[ i ];
str = [str stringByAppendingFormat:@"%@ : %.2f \\n", point.seriesName, point.dataY];
}
point = data[data.count - 1];
str = [str stringByAppendingFormat:@"%@ : %.2f", point.seriesName, point.dataY];
view.content.text = str;
view.content.numberOfLines = 4;
}
}
}
@end
Using the Line Marker in your Chart
Now that we set up our own MarkerView and MarkerRender we can add the line marker to our chart in code.
MyMarkerView *view = [[MyMarkerView alloc] initWithLineMarker:chart.lineMarker];
view.markerRender = [[MyChartMarkerRender alloc] initWithView:view];
[chart addSubview:view];
chart.lineMarker.content = view;
This allows us to use the line marker with our chart, but there is further configuration that is possible. The line marker has properties that dictate alignment, interaction, lines, seriesIndex, color, and position. Alignment can either be automatic or snap into a quadrant (aligned to the top left, top right, bottom left, bottom right of the selected point). Interaction can either be move (where a user can either tap or drag to move the line marker), drag (where the user actively selects the line marker and drags it), or no interaction at all. Finally the line option gives you the choice of displaying a horizontal line, vertical line, both line types, or no lines at all. SeriesIndex sets which series your line marker will snap to, thus if it is set to 0 it will snap along points in the first series. If you do not wish to have the line marker snap to points along any series and instead move freely you can set the seriesIndex to -1. I've configured the following chart to show both line types, snap to series index 1 (wetsuits in the chart), set the interaction to move, and configured the line marker to automatically position itself. After some configuration, the resulting code should look like this:
chart.lineMarker.isVisible = true;
chart.lineMarker.alignment = XuniChartMarkerAlignmentAuto;
chart.lineMarker.lines = XuniChartMarkerLinesBoth;
chart.lineMarker.interaction= XuniChartMarkerInteractionMove;
chart.lineMarker.dragContent = true;
chart.lineMarker.seriesIndex = 1;
chart.lineMarker.verticalLineColor = [UIColor grayColor];
Summing up Line Markers
Line markers are a relatively simple way of enhancing your mobile charts and are an easy way of optimizing screen real estate and simplifying the touch interactions necessary for users to interact with their data. Xuni 2015 v3 brings many exciting updates to Xuni so be sure to check out our other content for the release.