tags:

views:

3635

answers:

6

I want to draw charts like pie charts to display stats in my Android app. As Android doesn't support Swing and AWT, i wonder how can i draw charts in Android? Please note that i don't want to use a third party tool.

A: 

This is something i have come up with after looking into API Demos:

package com.examples.piechart;

import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Bundle; import android.view.View;

public class PieChart extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); }

private static class SampleView extends View{

     private Paint[] mPaints;
     private Paint mFramePaint;
     private boolean[] mUseCenters;
     private RectF[] mOvals;
     private RectF mBigOval;
     private float mStart;
     private float mSweep;
     private int mBigIndex;

     private static final float SWEEP_INC = 2;
     private static final float START_INC = 30;

     public SampleView(Context context) {
         super(context);

         mPaints = new Paint[4];
         mUseCenters = new boolean[4];
         mOvals = new RectF[4];

         mPaints[0] = new Paint();
         mPaints[0].setAntiAlias(true);
         mPaints[0].setStyle(Paint.Style.FILL);
         mPaints[0].setColor(0x88FF0000);
         mUseCenters[0] = false;

         mPaints[1] = new Paint(mPaints[0]);
         mPaints[1].setColor(0x8800FF00);
         mUseCenters[1] = true;

         mPaints[2] = new Paint(mPaints[0]);
         mPaints[2].setStyle(Paint.Style.STROKE);
         mPaints[2].setStrokeWidth(4);
         mPaints[2].setColor(0x880000FF);
         mUseCenters[2] = false;

         mPaints[3] = new Paint(mPaints[2]);
         mPaints[3].setColor(0x88888888);
         mUseCenters[3] = true;

         mBigOval = new RectF(40, 10, 280, 250);

         //mOvals[0] = new RectF( 10, 270,  70, 330);
         mOvals[1] = new RectF( 90, 270, 150, 330);
         mOvals[2] = new RectF(170, 270, 230, 330);
         mOvals[3] = new RectF(250, 270, 310, 330);

         mFramePaint = new Paint();
         mFramePaint.setAntiAlias(true);
         mFramePaint.setStyle(Paint.Style.STROKE);
         mFramePaint.setStrokeWidth(0);
     }

     private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,
                           Paint paint) {
         canvas.drawRect(oval, mFramePaint);
         canvas.drawArc(oval, mStart, mSweep, useCenter, paint);

     }

     @Override protected void onDraw(Canvas canvas) {
         canvas.drawColor(Color.WHITE);

         drawArcs(canvas, mBigOval, mUseCenters[1],
                  mPaints[1]);
        /* 
         for (int i = 0; i < 2; i++) {
             drawArcs(canvas, mOvals[i], mUseCenters[i], mPaints[i]);
             drawArcs(canvas, mOvals[1], mUseCenters[1], mPaints[1]);
             }
         */

         drawArcs(canvas, mOvals[1], mUseCenters[1], mPaints[1]);
         mSweep += SWEEP_INC;
         if (mSweep > 360) {
             mSweep -= 360;
             mStart += START_INC;
             if (mStart >= 360) {
                 mStart -= 360;
             }
             mBigIndex = (mBigIndex + 1) % mOvals.length;
         }
         invalidate();
     }
 }


};

Can someone improve it further?

Maxood
+1  A: 

This is something i have come up with after looking into API Demos:

package com.examples.piechart;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;

class GraphicsActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstance)
    {



    }

    @Override 
    public void setContentView(View view)
    {
        if (false)
        {
            ViewGroup vg = new PictureLayout(this);
            vg.addView(view);
            view = vg;

        }

        super.setContentView(view);

    }
};


/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.examples.piechart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;


public class PictureLayout extends ViewGroup {
    private final Picture mPicture = new Picture();

    public PictureLayout(Context context) {
        super(context);
    }

    public PictureLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }    

    @Override
    public void addView(View child) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("PictureLayout can host only one direct child");
        }

        super.addView(child);
    }

    @Override
    public void addView(View child, int index) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("PictureLayout can host only one direct child");
        }

        super.addView(child, index);
    }

    @Override
    public void addView(View child, LayoutParams params) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("PictureLayout can host only one direct child");
        }

        super.addView(child, params);
    }

    @Override
    public void addView(View child, int index, LayoutParams params) {
        if (getChildCount() > 1) {
            throw new IllegalStateException("PictureLayout can host only one direct child");
        }

        super.addView(child, index, params);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int count = getChildCount();

        int maxHeight = 0;
        int maxWidth = 0;

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }

        maxWidth += getPaddingLeft() + getPaddingRight();
        maxHeight += getPaddingTop() + getPaddingBottom();

        Drawable drawable = getBackground();
        if (drawable != null) {
            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
        }

        setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
                resolveSize(maxHeight, heightMeasureSpec));
    }

    private void drawPict(Canvas canvas, int x, int y, int w, int h,
                          float sx, float sy) {
        canvas.save();
        canvas.translate(x, y);
        canvas.clipRect(0, 0, w, h);
        canvas.scale(0.5f, 0.5f);
        canvas.scale(sx, sy, w, h);
        //canvas.drawPicture(mPicture);
        //canvas.restore();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight()));
        mPicture.endRecording();

        int x = getWidth()/2;
        int y = getHeight()/2;

        if (false) {
            canvas.drawPicture(mPicture);
        } else {
            drawPict(canvas, 0, 0, x, y,  1,  1);
            drawPict(canvas, x, 0, x, y, -1,  1);
            drawPict(canvas, 0, y, x, y,  1, -1);
            drawPict(canvas, x, y, x, y, -1, -1);
        }
    }

    @Override
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
        location[0] = getLeft();
        location[1] = getTop();
        dirty.set(0, 0, getWidth(), getHeight());
        return getParent();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //final int count = super.getChildCount();

        for (int i = 0; i < 1/*count*/; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                final int childLeft = getPaddingLeft();
                final int childTop = getPaddingTop();
                child.layout(childLeft, childTop,
                        childLeft + child.getMeasuredWidth(),
                        childTop + child.getMeasuredHeight());

            }
        }
    }
}


package com.examples.piechart;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;

public class PieChart extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(new SampleView(this));


    }

    private static class SampleView extends View{

         private Paint[] mPaints;
         private Paint mFramePaint;
         private boolean[] mUseCenters;
         private RectF[] mOvals;
         private RectF mBigOval;
         private float mStart;
         private float mSweep;
         private int mBigIndex;

         private static final float SWEEP_INC = 2;
         private static final float START_INC = 0;

         public SampleView(Context context) {
             super(context);

             mPaints = new Paint[4];
             mUseCenters = new boolean[4];
             mOvals = new RectF[4];

             mPaints[0] = new Paint();
             mPaints[0].setAntiAlias(true);
             mPaints[0].setStyle(Paint.Style.FILL);
             mPaints[0].setColor(0x88FF0000);
             mUseCenters[0] = false;

             mPaints[1] = new Paint(mPaints[0]);
             mPaints[1].setColor(0x8800FF00);
             mUseCenters[1] = true;

             mPaints[2] = new Paint(mPaints[0]);
             mPaints[2].setStyle(Paint.Style.STROKE);
             mPaints[2].setStrokeWidth(4);
             mPaints[2].setColor(0x880000FF);
             mUseCenters[2] = false;

             mPaints[3] = new Paint(mPaints[2]);
             mPaints[3].setColor(0x88888888);
             mUseCenters[3] = true;

             mBigOval = new RectF(40, 10, 280, 250);

             //mOvals[0] = new RectF( 10, 270,  70, 330);
             mOvals[1] = new RectF( 90, 270, 150, 330);
             mOvals[2] = new RectF(170, 270, 230, 330);
             mOvals[3] = new RectF(250, 270, 310, 330);

             mFramePaint = new Paint();
             mFramePaint.setAntiAlias(true);
             mFramePaint.setStyle(Paint.Style.STROKE);
             mFramePaint.setStrokeWidth(0);
             super.invalidate();

         }

         private void drawArcs(Canvas canvas, RectF oval, boolean useCenter,
                               Paint paint) {
             canvas.drawRect(oval, mFramePaint);
             canvas.drawArc(oval, mStart, mSweep, useCenter, paint);

         }

         @Override protected void onDraw(Canvas canvas) {
             canvas.drawColor(Color.WHITE);

             drawArcs(canvas, mBigOval, mUseCenters[1],
                      mPaints[1]);
            /* 
             for (int i = 0; i < 2; i++) {
                 drawArcs(canvas, mOvals[i], mUseCenters[i], mPaints[i]);
                 drawArcs(canvas, mOvals[1], mUseCenters[1], mPaints[1]);
                 }
             */

             drawArcs(canvas, mOvals[1], mUseCenters[1], mPaints[1]);
             mSweep += SWEEP_INC;
             if (mSweep > 180) {
                 mSweep -= 180;
                 mStart = START_INC;
                /* if (mStart >= 360) {
                     mStart -= 360;
                 }*/
                 //mBigIndex = (mBigIndex + 1) % mOvals.length;
             }


             invalidate();
         }
     }


    };

Now whats really happening is that a pie is drawn and drawn again and again. I just need to stop it once it is drawn and thats it. Can anybody help?

Maxood
You are asking another question in this answer. Try to write up the answer in this question and then post your new question as a new question on the site.
Janusz
+3  A: 

This is pretty much identical to this question: http://stackoverflow.com/questions/424752/any-good-graphing-packages-for-android/1856369#1856369

You might want to look at those answers.

mbaird
+1  A: 

Try to use aiCharts library http://www.artfulbits.com/android/aiCharts.aspx - the best charts library for Android known by me... a lot of samples, nice documentation. ArtfulBits support team answer on all questions in a minutes...

AlexK
Thanks for advertising your library.
Janusz
+1  A: 

Hi there,

I've got a solution: http://w2davids.wordpress.com/creating-charts-with-droidcharts-for-android/

Thanks! Seems like a good solution. I'll look into it then discuss it with you further.
Maxood
A: 

hi all....... think this tutorial would help :)

http://xebee.xebia.in/2010/08/31/exploring-android-charting-and-graphs-solutions/

wavesamir