Draw Pie Chart using Canvas and Third party Library in Android

Graph plays a very important role in showing data in  Graphical view. User generally find comparison  in a graph  very interesting. It gives a clear view of something going up or down or how things related to each other or what is previous record  and what is next coming forecast for that etc.

But in android there is no graph  related API. We can draw graph in android by using general android API. The other way is to use third party graph library to draw the graph.

So finally we have two option to draw graph in android

1. Draw graph by using canvas in android.

2. Draw graph by using third party API ( Ex. AChartEngine, AndroidPlot, Google Chart , AFreeChart etc)

I'll share both example with you.

1. Draw Graph by using Canvas in Android.

Simple Pie Chart example without using any external jar in android. Here we are creating chart using Canvas class in android.


PieChartActivity,java

package com.example.homeappliancesusage;
 
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

 
public class PieChartActivity  extends Activity implements PieChartView.Callback {

float[] datapoints = { 250, 230, 150, 300, 160 };
String names[] = { "Anil", "Deepak", "preet", "Simran" , "Amit"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_piechart);
 
PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart);
pieChartView.setDataPoints(datapoints, names);

// Because this activity is of the type PieChartView.Callback
pieChartView.setCallback(PieChartActivity.this);

}
 
@Override
public void onDrawFinised(DataColorSet[] data) {
// When the chart has finished drawing it will return the colors used
// and the value along (for our key)
LinearLayout keyContainer = (LinearLayout) findViewById(R.id.key);
if (keyContainer.getChildCount() > 0)
keyContainer.removeAllViews(); // Empty all views if any found

for (int i = 0; i < data.length; i++) {
DataColorSet dataColorSet = data[i];

LinearLayout keyItem = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.key_item, null);
LinearLayout colorView = (LinearLayout) keyItem.findViewById(R.id.color);
TextView name = (TextView) keyItem.findViewById(R.id.names);
TextView valueView = (TextView) keyItem.findViewById(R.id.value);

colorView.setBackgroundColor(Color.parseColor("#" + dataColorSet.getColor()));
name.setText("" + dataColorSet.getName());
valueView.setText("" + dataColorSet.getDataValue());

// Add the key to the container
keyContainer.addView(keyItem, i);
}
}

@Override
public void onSliceClick(DataColorSet data) {
// When the slice has been clicked. You can decide to call another
// activity here. We'll just make a toast
Toast.makeText(this, "Value is: " + data.getDataValue(), Toast.LENGTH_LONG).show();
}

}


PieChartView.java

package com.example.homeappliancesusage;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class PieChartView extends View {
private Paint slicePaint;
private int[] sliceClrs = {  Color.parseColor("#64E6C9"), Color.parseColor("#FEB02C"), Color.parseColor("#56CAFE"),
Color.parseColor("#FC69FC"),  Color.parseColor("#FA7A57") };
private RectF rectf; // Our box
private float[] datapoints; // Our values
private String[] names;
private int alphaIndex = -1;
private Bitmap canvasBitmap;

// The data and color set object to be returned after the drawing is done
private DataColorSet[] dataColorSet;

// Our Callback object
private Callback callback;

public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
slicePaint = new Paint();
slicePaint.setAntiAlias(true);
slicePaint.setDither(true);
slicePaint.setStyle(Style.FILL);
}

@Override
protected void onDraw(Canvas canvas) {
if (this.datapoints != null) {
int startTop = 0;
int startLeft = 0;
int endBottom = getWidth();
int endRight = endBottom; // To make this an equal square
// Create the box

rectf = new RectF(startLeft, startTop, endRight, endBottom); // Creating
// the
// box

float[] scaledValues = scale(); // Get the scaled values
String names[] = names();
float sliceStartPoint = 0;

// Initialize colors used
dataColorSet = new DataColorSet[scaledValues.length];

for (int i = 0; i < scaledValues.length; i++) {
slicePaint.setColor(sliceClrs[i]); // Remember to set the paint
// color first
// Let's check the alphaIndex if it is greater than or equal to
// 0 first
if (alphaIndex > -1 && alphaIndex == i)
slicePaint.setAlpha(150); // Then slice at i was pressed
else
slicePaint.setAlpha(255);

canvas.drawArc(rectf, sliceStartPoint, scaledValues[i], true, slicePaint); // Draw slice
sliceStartPoint += scaledValues[i]; // Update starting point of
// the next slice

// Add DataColorSet object to return after draw
dataColorSet[i] = new DataColorSet( Integer.toHexString(sliceClrs[i]), datapoints[i], names[i] );
}

// Build and get what's drawn on the canvas as a bitmap
buildDrawingCache(true);
canvasBitmap = getDrawingCache(true);

// After the drawing has been done use your Callback's
// onDrawFinished() method
callback.onDrawFinised(dataColorSet);
}
}

public void setCallback(Callback callback) {
this.callback = callback; // To initialize the callback object on your
// activity
}

@Override
public boolean onTouchEvent(MotionEvent event) {
// If the finger is on the screen
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Get x and y coordinates of where the finger touched
int pixelX = (int) (Math.floor(event.getX()));
int pixelY = (int) (Math.floor(event.getY()));

if (canvasBitmap != null) {
// Get the pixel color
int pixel = canvasBitmap.getPixel(pixelX, pixelY);

// Convert the pixel into a hex color string
String pixelHex = Integer.toHexString(pixel); // This will
// return a
// hexa-decimal
// of the bitmap

// Set the alpha index so that we know which slice to change the
// opacity of
setAlphaIndex(pixelHex);
}

invalidate();
}

// If the finger is off the screen
if (event.getAction() == MotionEvent.ACTION_UP) {
alphaIndex = -1; // This is a flag to reset the view alphas to
// normal
invalidate();
}

return true;
}

public void setDataPoints(float[] datapoints, String[] names) {
this.datapoints = datapoints;
this.names = names;
invalidate(); // Tells the chart to redraw itself
}

private void setAlphaIndex(String pixelHex) {
for (int i = 0; i < sliceClrs.length; i++) {
String tempHex = Integer.toHexString(sliceClrs[i]);
if (pixelHex.equals(tempHex)) {
alphaIndex = i; // This is the slice index to tweak the opacity
// of

// Call our slice click here because the slice has been found
callback.onSliceClick(dataColorSet[i]);

break;
}
}
}

private float[] scale() {
float[] scaledValues = new float[this.datapoints.length];

float total = getTotal(); // Total all values supplied to the chart
for (int i = 0; i < this.datapoints.length; i++) {
scaledValues[i] = (this.datapoints[i] / total) * 360; // Scale each
// value
}
return scaledValues;
}

private float getTotal() {
float total = 0;
for (float val : this.datapoints)
total += val;
return total;
}

private String[] names() {
String[] names = new String[this.names.length];
for (int i = 0; i < this.names.length; i++) {
names[i] = (this.names[i]);
}
return names;

}

// Our Callback interface
public interface Callback {
public void onDrawFinised(DataColorSet[] data);

public void onSliceClick(DataColorSet data);
}

}



DataColorSet,java

package com.example.homeappliancesusage;

public class DataColorSet {
private String color;
private float dataValue;

private String name;

public DataColorSet() {
}

public DataColorSet(String color, float dataValue, String name) {
this.dataValue = dataValue;
this.color = color;
this.name = name;
}

public void setColor(String color) {
this.color = color;
}

public void setDataValue(float dataValue) {
this.dataValue = dataValue;
}

public String getColor() {
return this.color;
}

public float getDataValue() {
return this.dataValue;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}



activity_piechart

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/layoutTop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/headerbg"
        android:orientation="horizontal"
        android:weightSum="5" >

        <com.example.homeappliancesusage.PieChartView
            android:id="@+id/pie_chart"
            android:layout_width="0dp"
            android:layout_height="300dp"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="20dp"
            android:layout_weight="2.7" />

        <LinearLayout
            android:id="@+id/key"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2.3"
            android:orientation="vertical" >
        </LinearLayout>
    </LinearLayout>

</LinearLayout>



key_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="2dp" >

    <LinearLayout
        android:id="@+id/color"
        android:layout_width="8dp"
        android:layout_height="8dp"
        android:layout_marginRight="4dp"
        android:orientation="horizontal" >
    </LinearLayout>

    <TextView
        android:id="@+id/names"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="vv"
        android:textColor="#000"
        android:textSize="12dp" />

    <TextView
        android:id="@+id/value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginRight="5dp"
        android:gravity="right"
        android:hint="1"
        android:textColor="#000"
        android:textIsSelectable="false"
        android:textSize="12dp" />

</LinearLayout>


Here is the output of the program





Happy Coding !!


2. Draw Graph by using Third party API.

coming soon..





Comments

  1. I found this very useful and adapted it slightly so I could generate the colours on the fly, what would have made it even better if I could have used the same class for more than one pie chart on an intent.

    ReplyDelete

Post a Comment

Popular posts from this blog

Carousel view in Android

Get Phone Contacts and display in Listview in Android