Tutorial (ANT-based)

Table of Contents

  1. Overview
  2. Introduction
  3. Installation
  4. Anatomy of Charts
  5. Drawing a Simple Chart
  6. Customizing Appearance
  7. Adding More Charts
  8. Adding Tooltips
  9. What's next?

Overview

This documentation provides a short tutorial that will explain the main concepts of the NChart3D framework as well as show you how to draw charts using NChart3D. NChart3D is a versatile charting engine for Android that lets you draw 2D and 3D interactive charts of different types according to your data. The usage of NChart3D is very simple and requires only a few lines of Java code to visualize your data in a convenient and beautiful form.

Warning! This tutorial covers the usage of NChart3D with Ant, which is now deprecated. Normally you have to use NChart3D with Gradle: link

Introduction

This tutorial will show you how to install NChart3D framework and build a simple project that displays some random data, how to customize the appearance of charts and how to manage the selection of data. This tutorial is partially based on the samples provided with .zip package that can be downloaded here. At the end of this tutorial you will be able to create a simple application that looks like this:

Screen 1

Installation

First, download the .zip archive and unzip it. There you can find NChart3D documentation, samples and libraries to include in your project.

NOTE: In this tutorial we assumed you have properly tuned environment. You may have to learn addition info about Android SDK installation and different build tools usage:

Despite the fact that IntelliJ Idea did not described on developer.android.com - it is friendly and powerful IDE for Android and Java.

Every sample contains Android application project (manifest, resources and sources folders) suitable for Apach ANT or ANT-based IDE. If you want to use Android Studio you have to create new project in another folder, then copy sources and resources from sample. Assembling manually with stand-alone Gradle doesn't covered by this tutorial.

Generally, if you want to use ANT you need to prepare project. To do this run android update project -p . --target android-19 in project's root.

You also need to complete project sctructure with NChart3D library located in libs directory. Exact project sctructure depends on your build-tools:

ANT Eclipse IntelliJ Idea Android Studio
Copy NChart3D.jar to ProjectRoot/libs ProjectRoot/libs ProjectRoot/libs ProjectRoot/app/libs
Copy folders with .so to ProjectRoot/libs ProjectRoot/libs ProjectRoot/libs ProjectRoot/src/YourAppModuleName/jniLibs
Add dependecy to NChart3D.jar no need ensure that your project tree is updated, then open "Project Properties - Java Build Path - Add JARs" and select ProjectRoot/libs/NChart3D.jar find NChart3D.jar in project tree and add it as library in it's context menu no need

To build project with ANT run ant debug. The .apk ready to be installed to your device will be created in bin directory.

This tutorial will show you how to create a project from scratch in Android Studio. Let's begin! Create a new project with Android API 14 or higher. Proceed with the "blank activity" template.

Copy the NChart3D library as described above. Project's structure should look like this

Then right-click the NChart3D.jar and select "Add As Library..." (like in Idea).

By the way - that's how it looks in Eclipse:

Now com.nchart3d.NChart package is available.

Make a test-run to check whether the project is able to build and run. You will see the blank application. Now your project is set up and you can start using the NChart3D framework.

Anatomy of Charts

Before we start, let’s explain a little bit of terminology.

Screen 3
  • Background — the color or gradient that fills the background.
  • Caption — the text label (that can have background and border) that is displayed on top of the chart.
  • Legend — the scrollable widget that contains the names and marker images of all the series on the chart.
  • Plot area — the area where the series are drawn.
  • Axes — axes that surrounds the plot area.
  • Axes ticks — ticks that divide axes into pieces. There are major and minor ticks.
  • Axes grid lines — lines on the plot area that are parallel to the axes and start in the major ticks.
  • Axes labels — labels of the axes ticks.
  • Axes captions — captions of the axes.
  • Series — data visualizers.
  • Series’ points — individual values in the series.
  • Tooltip — a label on the chart displaying information about the chart point.

Drawing a Simple Chart

Let’s draw a simple chart. First, replace content of layout file activity_nchart.xml with the following content:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.nchart3d.NChart.NChartView
    android:id="@+id/nchart3d"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent" />
</LinearLayout>

The main class of NChart3D framework is called NChart and its instance is accessible from the NChartView. NChartView is the indirect subclass of android.opengl.GLSurfaceView that represents everything needed to display the chart in your views hierarchy. You can even manually create an NChartView instance, place it anywhere you want and then communicate with the chart through the corresponding property of that instance. NChartView instance that is created by the .xml layout inflation could be accessed like this

NChartView chart = (NChartView)findViewById(R.id.nchart3d);

After that, add the internal field mNChartView of the NChartView type to the main activity and override the onCreate method. There you can assign value to mNChartView after setContentView call like this:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_nchart);
    mNChartView = (NChartView)findViewById(R.id.nchart3d);
}

You can customize the chart through the mNChartView.getChart() property. If you have a license key, set it to the chart like this:

mNChartView.getChart().setLicenseKey("Your license key");

You may want to add some margin to the chart to get a spacing from the screen borders:

mNChartView.getChart().getCartesianSystem().setMargin(new NChartMargin(10, 10, 10, 10));

You may switch on anti-aliasing (that is off by default). It will not hurt performance, because the anti-aliasing algorithm is adaptive, so it is recommended to switch it on to get better visual quality of the image. Add the following line of code:

mNChartView.getChart().setShouldAntialias(true);

You should create a series that will be displayed. First, create only one column series and assign some brush that will fill this series with color. For example, let this series be green:

NChartColumnSeries series = new NChartColumnSeries();
series.setBrush(new NChartSolidColorBrush(Color.argb(255, 0, 192, 96)));

You should assign a data source to that series. There is an interface called NChartSeriesDataSource that you should implement to build a data source. For example, you can make a data source from your activity simply by adding implements NChartSeriesDataSource to its declaration. And then add two methods that will supply data and names for the series:

Random random = new Random();
public NChartPoint[] points(NChartSeries nChartSeries) {
    NChartPoint[] result = new NChartPoint[11];
    for (int i = 0; i <= 10; ++i)
        result[i] = new NChartPoint(NChartPointState.PointStateAlignedToXWithXY(i, random.nextInt(30) + 1), nChartSeries);
    return result;
}
public String name(NChartSeries nChartSeries) {
    return "My series";
}
public Bitmap image(NChartSeries nChartSeries) {
    return null;
}

As you can see, the first method generates an array of points with some random data. Each point can contain an array of states representing the changes of data in time. However in this tutorial we will create only one state for each point, which will be automatically the current one. Each state holds the actual data. For 2D columns the data are represented by X and Y values. We want the columns to be aligned to the X axis to make them look like "paling", so we use integer X values. The height of columns is "free", so normally double values are used, but in our case also integers are used. Feel free to experiment with different values and see what happens. The second method generates names for series to allow NChart3D to build the legend. Now, when the data source is ready, assign it to the series you have created and finally add series to the chart:

series.setDataSource(this);
mNChartView.getChart().addSeries(series);

That's almost all we need to visualize the data. The only thing we've missed is to update data in the chart:

mNChartView.getChart().updateData();

This will force the NChart3D framework to process the data and build the visual appearance of the series. You should call this method any time the data was changed. Now you can build and run your application and see what happens. You should get the following result:

Screen 4

Customizing Appearance

As you can see, the values on the axes are calculated automatically. Let's customize them and display some labels on the X axis! The axes as well as the series can have their own data sources. These data sources can supply custom minimums / maximums or custom strings for labels of the ticks. Add interface NChartValueAxisDataSource to your activity:

public class NChart extends Activity implements NChartSeriesDataSource, NChartValueAxisDataSource

Next implement methods. Return not-null values from a method ticks that will supply the strings used for ticks' labels. We have 11 points in the series, so we should supply 11 strings. Let's also add captions to the axes. Method name will supply names for the X and Y axes.

public String name(NChartValueAxis nChartValueAxis) {
    switch (nChartValueAxis.getKind()) {
        case X:
            return "X Axis";
        case Y:
            return "Y Axis";
        default:
            return null;
    }
}
public Number min(NChartValueAxis nChartValueAxis) {
    return null;
}
public Number max(NChartValueAxis nChartValueAxis) {
    return null;
}
public Number step(NChartValueAxis nChartValueAxis) {
    return null;
}
public String[] ticks(NChartValueAxis nChartValueAxis) {
    switch (nChartValueAxis.getKind()) {
        case X:
            return new String[]{"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven"};
        default:
            return null;
    }
}
public Number length(NChartValueAxis nChartValueAxis) {
    return null;
}
public String doubleToString(double v, NChartValueAxis nChartValueAxis) {
    return null;
}

Of course, you should set the data source to the axes you want to customize. You can do this by adding the following line before your updateData call:

mNChartView.getChart().getCartesianSystem().getXAxis().setDataSource(this);
mNChartView.getChart().getCartesianSystem().getYAxis().setDataSource(this);

You can also play with the colors of chart. For example, let's change the background to the gray-to-white gradient. For this, you can create a gradient brush and assign it to the chart's background property:

mNChartView.getChart().setBackground(new NChartLinearGradientBrush(Color.argb(255, 160, 160, 160), Color.WHITE));

You may use the multicolor gradients as well. See the documentation for NChartLinearGradientBrush for details. You can also add a border for your series, like this:

series.setBorderThickness(2.0f);
series.setBorderBrush(new NChartSolidColorBrush(Color.BLACK));

Now add the caption to the chart by adding another lines to the onCreate method:

mNChartView.getChart().getCaption().setMargin(new NChartMargin(0, 0, 0, 10));
mNChartView.getChart().getCaption().setText("NChart3D");

You will get the following result:

Screen 5

Adding More Charts

Now let's add more series to the chart. Just create another series of different types, for example one area and one line. To do this, add the following code after the creation of the first series:

// Second
NChartAreaSeries series2 = new NChartAreaSeries();
series2.setBrush(new NChartSolidColorBrush(Color.argb(255, 255, 128, 0)));
series2.getBrush().setOpacity(0.7f);
series2.setDataSource(this);
mNChartView.getChart().addSeries(series2);
// Third
NChartLineSeries series3 = new NChartLineSeries();
series3.setBrush(new NChartSolidColorBrush(Color.RED));
series3.setLineThickness(3.0f);
series3.setDataSource(this);
mNChartView.getChart().addSeries(series3);

You should get the following result:

Screen 6

As you can see, three series of different types appear on the chart. Wait, what? The names in the legend are all the same! Let's fix it. First, add the tag for each series like this:

series.tag = 1;
series2.tag = 2;
series3.tag = 3;

And then change the name(NChartSeries nChartSeries) method to the following:

public String name(NChartSeries nChartSeries) {
    return "My series " + nChartSeries.tag;
}

This will add the numbers to the series' names that appear in the legend.

Adding Tooltips

It's time to add tooltips that will appear and disappear by tapping chart points and display some information, for example, the name of a series and the current Y value. To handle which chart points are selected when tapped, NChartDelegate is used. Declare this interface for your activity:

public class NChart extends Activity implements NChartSeriesDataSource, NChartValueAxisDataSource, NChartDelegate

Then implement three required methods of this interface:

public void pointSelected(NChart nChart, NChartPoint nChartPoint) {
    if (m_prevSelectedPoint != null && m_prevSelectedPoint.getTooltip() != null)
        m_prevSelectedPoint.getTooltip().setVisibleAnimated(false, 0.25f);
    if (nChartPoint != null) {
        if (nChartPoint.getTooltip() != null) {
            if (nChartPoint == m_prevSelectedPoint)
                m_prevSelectedPoint = null;
            else {
                m_prevSelectedPoint = nChartPoint;
                updateTooltipText(nChartPoint);
                nChartPoint.getTooltip().setVisibleAnimated(true, 0.25f);
            }
        } else {
            m_prevSelectedPoint = nChartPoint;
            nChartPoint.setTooltip(createTooltip());
            updateTooltipText(nChartPoint);
            nChartPoint.getTooltip().setVisibleAnimated(true, 0.25f);
        }
    } else {
        m_prevSelectedPoint = null;
    }
}
public void didEndAnimating(NChart nChart, Object o, NChartAnimationType animationType) {
}
public void timeIndexChanged(NChart nChart, double v) {
}
public void rangeChanged(NChart chart){
}
public void didMove(NChart chart) {
}

The logic here is pretty straightforward. We hide old tooltip (if any) with animation and then show the new one or do nothing if the selected point is the one we selected before (so second tap to the same point hides the tooltip). To make this work, we should store the previously selected point somewhere. Let's use internal variable called m_prevSelectedPoint of type NChartPoint for that. Also we will need two additional methods to create and update a tooltip. You may use some initial settings for the tooltip like this:

private NChartTooltip createTooltip() {
    NChartTooltip result = new NChartTooltip();
    result.setBackground(new NChartSolidColorBrush(Color.WHITE));
    result.getBackground().setOpacity(0.9f);
    result.setPadding(new NChartMargin(10.0f, 10.0f, 10.0f, 10.0f));
    result.setBorderColor(Color.argb(255, 128, 128, 128));
    result.setBorderThickness(1.0f);
    result.setFont(new NChartFont(16));
    return result;
}

And then you should update the text in the tooltip:

private void updateTooltipText(NChartPoint point) {
    point.getTooltip().setText(String.format("%s : %.2f", point.getSeries().getName(), point.getCurrentState().getDoubleY()));
}

As you can see, you can display any information in the tooltip you want. Finally set the delegate for chart by adding the following line to the onCreate method:

mNChartView.getChart().setDelegate(this);

And that's it! You should get something like this:

Screen 1

What's next?

You can find more information about using the NChart3D framework in samples on package. If you have any questions, feel free to contact us.