본문 바로가기
PROGRAM/Mobile

achartengine을 사용해 안드로이드에서 챠트를 그려봅시다.

by ojava 2011. 6. 27.
반응형

안드로이드를 기반으로 한 어플리케이션을 만들게 될 기회가 생겼습니다.
어떠한 내용에 대해서 관리해주는 어플이었기 때문에 눈으로 보여줘야 할 필요가 있었는데요~~

이 때문에 안드로이드 관련 챠트를 찾아보게 되었습니다. 

aiCharts가 굉장히 깔끔했고 다양한 형태를 지원했지만.. 유료이기에 ㅠ_ㅠ
오픈소스 위주로 찾던 중 achartengine에 대해서 알게되었습니다.


http://code.google.com/p/achartengine/

지금까지도 계속 개발되어지고 있고 오픈소스이다보니
사용자가 스스로 변경 및 발전시켜서 사용이 가능하다는 게 큰 장점입니다.
물론 노력하고 능력있는 사람들이 더 좋은 결과물을 얻는게 당연하지만요.


현재 AChartEngine은 아래와 같은 내용들을 지원합니다.


  • line chart
  • area chart
  • scatter chart
  • time chart
  • bar chart
  • pie chart
  • bubble chart
  • doughnut chart
  • range (high-low) bar chart
  • dial chart / gauge
     

  •   


    자세한 내용은 위의 링크를 통해 만나보실 수 있으며, 다운로드도 매우 간단하게 받을 수 있습니다.





    저의 경우는 최신 버전인 achartengine-0.6.0 을 사용하여 챠트를 구현하였습니다.
    기본적으로 지원하는 챠트에 대해서 직접 eclipse에 붙여서 사용해보시고 싶으시다면

    achartengine-0.6.0-demo.jar 파일을 다운받으셔서 import 해보시면 내용을 보실 수 있습니다.
    물론 안드로이드 환경이 구현되어 있어야 하며, demo.jar파일에 있는
    AndroidManifest.xml 파일의 내용이 핵심적이라는 건 아시겠지영?  




    차트모양을 캡쳐해보았습니다. 저는 achartengine에서 지원하는 TimeChart를 extends 받아서 구현했습니다.






    걷기운동내용에 대해서 사용자가 직접 내역을 추가하고 그에 대한 관리를 하는 어플이었고
    세번째 탭에서 볼 수 있는 내역 추가에서 사용자가 추가하게 되면 현재 보시는 운동일지라는
    탭에서 achartengine을 띄워 챠트를 통해 현재 상태를 확인할 수 있는 구조로 구현되었습니다.



    demo를 실행해보신분은 아시겠지만 기본적인 각각의 chart의 구현모습은 IChart라는 interface를 구현한
    AbstractDemoChart를 extends 받은 모습입니다. 하지만 이는 demo에서 list로 구현된 내용을 불러오기 위한 것으로
    여러가지 챠트를 한 번에 보여줄 때 적합한 형태이므로 원하는 챠트의 모양을 염두에 두시고 그 챠트를 extends 받으시면 됩니다.

    먼저 첨부하는 내용은 제가 이용한 TimeChart의 핵심 메소드입니다.

      /**

       * Executes the chart demo.

       * 

       * @param context the context

       * @return the built intent

       */

      public Intent execute(Context context) {

        String[] titles = new String[] { "New tickets", "Fixed tickets" };

        List<Date[]> dates = new ArrayList<Date[]>();

        List<double[]> values = new ArrayList<double[]>();

        int length = titles.length;

        for (int i = 0; i < length; i++) {

          dates.add(new Date[12]);

          dates.get(i)[0] = new Date(108, 9, 1);

          dates.get(i)[1] = new Date(108, 9, 8);

          dates.get(i)[2] = new Date(108, 9, 15);

          dates.get(i)[3] = new Date(108, 9, 22);

          dates.get(i)[4] = new Date(108, 9, 29);

          dates.get(i)[5] = new Date(108, 10, 5);

          dates.get(i)[6] = new Date(108, 10, 12);

          dates.get(i)[7] = new Date(108, 10, 19);

          dates.get(i)[8] = new Date(108, 10, 26);

          dates.get(i)[9] = new Date(108, 11, 3);

          dates.get(i)[10] = new Date(108, 11, 10);

          dates.get(i)[11] = new Date(108, 11, 17);

        }

        values.add(new double[] { 142, 123, 142, 152, 149, 122, 110, 120, 125, 155, 146, 150 });

        values.add(new double[] { 102, 90, 112, 105, 125, 112, 125, 112, 105, 115, 116, 135 });

        length = values.get(0).length;

        int[] colors = new int[] { Color.BLUE, Color.GREEN };

        PointStyle[] styles = new PointStyle[] { PointStyle.POINT, PointStyle.POINT };

        XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);

        setChartSettings(renderer, "Project work status", "Date", "Tickets", dates.get(0)[0].getTime(),

            dates.get(0)[11].getTime(), 50, 190, Color.GRAY, Color.LTGRAY);

        renderer.setXLabels(5);

        renderer.setYLabels(10);

        renderer.setDisplayChartValues(true);

        return ChartFactory.getTimeChartIntent(context, buildDateDataset(titles, dates, values),

            renderer, "MM/dd/yyyy");

      }



    보시면 아시겠지만 TimeChart에 들어갈 시간이 입력되는 부분과 X, Y축의 범례와 제목이 들어가는 부분 등
    알차게 구성된 내용을 볼 수 있습니다. 색상 선정과 여백 입력등이 사용자가 직접 설정가능하도록 되어있습니다.



    밑으로 보시는 내용은 제가 변형한 내용입니다. demo와는 다르게 필요한 내용에 대해서
    전체적으로 extends 받고 있지않으므로 그러한 내용들에 대해서도 구현하셔야 합니다.
    저의 경우에는 입력하는 내용에 따라 자동적으로 챠트에 반영되어야 하는 내용임을 참고하고 보시길 바랍니다.


    /**

     * ExersiceChart : 운동일지 구현 시 사용되는 achart

     * TimeChart : 각 일자별로 소모 Kcal와 걸은 거리(KM) 표시

     * 

     * @author 오혜영

     */

    public class ExerciseChart extends TimeChart {

       /** The number of milliseconds in a day. */

       public static final long DAY = 24 * 60 * 60 * 1000;

       /** The date format pattern to be used in formatting the X axis  labels. */

       private String mDateFormat;

       private UserDBControl mWalking;

       SQLiteDatabase db;

       double[] sumKcalValue, sumAmountValue;

       Date [] dateValue;

       int i = 0;


      public ExerciseChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type, String format) {

        super(dataset, renderer);

        mDateFormat = format;

    // TODO Auto-generated constructor stub

    }

     

    /**

    * Builds an XY multiple series renderer.

    * @param colors the series rendering colors

    * @param styles the series point styles

    * @return the XY multiple series renderers

    */

    protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles) {

     XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();

     renderer.setAxisTitleTextSize(16);

     renderer.setChartTitleTextSize(20);

     renderer.setLabelsTextSize(15);

     renderer.setLegendTextSize(15);

     renderer.setPointSize(6f);

     renderer.setMargins(new int[] { 30, 30, 25, 0 });

     int length = colors.length;

     for (int i = 0; i < length; i++) {

       XYSeriesRenderer r = new XYSeriesRenderer();

       r.setColor(colors[i]);

       r.setPointStyle(styles[i]);

       renderer.addSeriesRenderer(r);

     }

     return renderer;

    }

    /**

    * Sets a few of the series renderer settings.

    * @param renderer the renderer to set the properties to

    * @param title the chart title

    * @param xTitle the title for the X axis

    * @param yTitle the title for the Y axis

    * @param xMin the minimum value on the X axis

    * @param xMax the maximum value on the X axis

    * @param yMin the minimum value on the Y axis

    * @param yMax the maximum value on the Y axis

    * @param axesColor the axes color

    * @param labelsColor the labels color

    */

    protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,

       String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor,

       int labelsColor) {

     renderer.setChartTitle(title);

     renderer.setXTitle(xTitle);

     renderer.setYTitle(yTitle);

     renderer.setXAxisMin(xMin);

     renderer.setXAxisMax(xMax);

     renderer.setYAxisMin(yMin);

     renderer.setYAxisMax(yMax);

     renderer.setAxesColor(axesColor);

     renderer.setLabelsColor(labelsColor);

    }


      /**

       * Builds an XY multiple time dataset using the provided values.

       * 

       * @param titles the series titles

       * @param xValues the values for the X axis

       * @param yValues the values for the Y axis

       * @return the XY multiple time dataset

       */

      protected XYMultipleSeriesDataset buildDateDataset(String[] titles, List<Date[]> xValues,

          List<double[]> yValues) {

        XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();

        int length = titles.length;

        for (int i = 0; i < length; i++) {

          TimeSeries series = new TimeSeries(titles[i]);

          Date[] xV = xValues.get(i);

          double[] yV = yValues.get(i);

          int seriesLength = xV.length;

          for (int k = 0; k < seriesLength; k++) {

            series.add(xV[k], yV[k]);

          }

          dataset.addSeries(series);

        }

        return dataset;

      }



      /**

       * 각각의 그래프에 해당되는 범례 및 색상, 시각 입력

       * @param context the context

       * @return the built intent
       * @author 오혜영 

       */

      public Intent execute(Context context) {

        String[] titles = new String[] { "거리(Km)", "소모 Kcal" };

        List<Date[]> dates = new ArrayList<Date[]>();

        List<double[]> values = new ArrayList<double[]>();

        int length = titles.length;

        // TODO 1. 시작한 날로부터 지속적으로 날짜를 기록할 수 있도록 만들어 둘 것

    for (int i = 0; i < length; i++) {

    dates.add(new Date[dateValue.length]);

    for (int j=0; j<dateValue.length; j++) { 

    dates.get(i)[j] = dateValue[j];

    }

    }


        values.add(sumAmountValue);

        values.add(sumKcalValue);

        length = values.get(0).length;

        int[] colors = new int[] { Color.GREEN, Color.RED };

        PointStyle[] styles = new PointStyle[] { PointStyle.POINT, PointStyle.CIRCLE};

        XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);

        // TODO 2. 시작하는 날짜 및 시작하는 amount의 부분을 지정해줘야 함

        setChartSettings(renderer, "걷기운동과 소요 Kcal", "운동일자", "운동량 & Kcal", dates.get(0)[0].getTime(),

            dates.get(0)[dateValue.length-1].getTime(), 0, 1000, Color.GRAY, Color.LTGRAY);

        renderer.setXLabels(3);

        renderer.setYLabels(10);

        renderer.setDisplayChartValues(true);

        return ChartFactory.getTimeChartIntent(context, buildDateDataset(titles, dates, values),

            renderer, "yyyy.MM.dd");

      }




    데이터 입력부분은 제외하였습니다. 위의 내용에서 3개 정도의 추가적인 메소드가 들어갔는데,
    이 내용은 execute에서 필요한 내용으로 구현해주셔야 하는 부분입니다. 
    TODO를 통해서 표현한 부분은 각각의 데이터가 들어가야 하는 부분으로
    지속적으로 내용이 들어가는 부분이 아니라면 윗 부분에 첨부한 기존의 메소드 내용을 이용하셔도
    충분히 필요한 챠트를 구현하실 수 있으시리라 봅니다.



    해보면 매우 쉬운 작업인데 저도 제가 직접해보기 전까지는 매우 헤맸답니다 ㅠ_ㅠ
    혹시나 안드로이드에서 챠트를 구현하고자하고 achart에 대해서 찾아다니는 분이 계실까하여 올려봅니당.


    2011.06 오혜영 작성
    반응형

    'PROGRAM > Mobile' 카테고리의 다른 글

    링크 공유하기 : SMS 보내기, 클립보드에 복사하기  (0) 2019.03.09