• Tutorials
  • Tips & Tricks
  • Applications
  • News

Android Trainee

  • Tutorials
  • Tips & Tricks
  • Applications
  • News
Home  /  Tutorials  /  Draw Android pie Chart With Animation.
14 July 2015

Draw Android pie Chart With Animation.

Written by admin@androidtrainee
Tutorials android chart animation, android pie chart, chart, chartview, pie chart, pie chart animation Leave a Comment

Draw Android pie Chart With Animation.

 

—>  AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.barchart"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="22" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

 

IN Layout Folder

activity_main.xml

 


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:background="#ffffff">

<view
android:layout_width="fill_parent"
android:layout_height="wrap_content"
class="com.example.androidpiechart.PieView"
android:id="@+id/pie_view"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_margin="10dp" />


<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Random"
android:id="@+id/pie_button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/textView"
android:layout_above="@+id/pie_button"
android:layout_centerHorizontal="true" />

</RelativeLayout>

 

MyUtils.java


package com.example.barchart;


import android.content.Context;


public class MyUtils {

public static int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(dipValue * scale + 0.5f);
}

public static int px2dip(Context context, float pxValue){
final float scale = context.getResources().getDisplayMetrics().density;
return (int)(pxValue / scale + 0.5f);
}

public static int sp2px(Context context, float spValue) {
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}

}

 

MainActivity.java


package com.example.androidpiechart;

import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {
private TextView textView;
PieView pieView;
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textView);
pieView = (PieView)findViewById(R.id.pie_view);
button = (Button)findViewById(R.id.pie_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
randomSet(pieView);
}
});
set(pieView);
}
private void randomSet(PieView pieView){
ArrayList<PieHelper> pieHelperArrayList = new ArrayList<PieHelper>();
ArrayList<Integer> intList = new ArrayList<Integer>();
int totalNum = (int) (5*Math.random()) + 5;

int totalInt = 0;
for(int i=0; i<totalNum; i++){
int ranInt = (int)(Math.random()*10)+1;
intList.add(ranInt);
totalInt += ranInt;
}
for(int i=0; i<totalNum; i++){
pieHelperArrayList.add(new PieHelper(100f*intList.get(i)/totalInt));
}

pieView.selectedPie(PieView.NO_SELECTED_INDEX);
pieView.showPercentLabel(true);
pieView.setDate(pieHelperArrayList);
}

private void set(PieView pieView){
ArrayList<PieHelper> pieHelperArrayList = new ArrayList<PieHelper>();
pieHelperArrayList.add(new PieHelper(20, Color.BLACK));
pieHelperArrayList.add(new PieHelper(6));
pieHelperArrayList.add(new PieHelper(30));
pieHelperArrayList.add(new PieHelper(12));
pieHelperArrayList.add(new PieHelper(32));

pieView.setDate(pieHelperArrayList);
pieView.setOnPieClickListener(new PieView.OnPieClickListener() {
@Override
public void onPieClick(int index) {
if(index != PieView.NO_SELECTED_INDEX) {
textView.setText(index + " selected");
}else{
textView.setText("No selected pie");
}
}
});
pieView.selectedPie(2);
}

}

 

PieHelper.java


package com.example.androidpiechart;


public class PieHelper {

private float startDegree;
private float endDegree;
private float targetStartDegree;
private float targetEndDegree;
private String title;
private int color;
private float sweepDegree;

int velocity = 5;


public PieHelper(float percent){
this(percent, null, 0);
}

public PieHelper(float percent, int color){
this(percent, null, color);
}


PieHelper(float percent, String title){
this(percent, title, 0);
}


PieHelper(float percent, String title, int color){
this.sweepDegree = percent * 360 / 100;
this.title = title;
this.color = color;
}


PieHelper(float startDegree, float endDegree, PieHelper targetPie){
this.startDegree = startDegree;
this.endDegree = endDegree;
targetStartDegree = targetPie.getStartDegree();
targetEndDegree = targetPie.getEndDegree();
this.sweepDegree = targetPie.getSweep();
this.title = targetPie.getTitle();
this.color = targetPie.getColor();
}

PieHelper setTarget(PieHelper targetPie){
this.targetStartDegree = targetPie.getStartDegree();
this.targetEndDegree = targetPie.getEndDegree();
this.title = targetPie.getTitle();
this.color = targetPie.getColor();
this.sweepDegree = targetPie.getSweep();
return this;
}

void setDegree(float startDegree, float endDegree){
this.startDegree = startDegree;
this.endDegree = endDegree;
}

boolean isColorSetted(){return color != 0;}

boolean isAtRest(){
return (startDegree==targetStartDegree)&&(endDegree==targetEndDegree);
}

void update(){
this.startDegree = updateSelf(startDegree, targetStartDegree, velocity);
this.endDegree = updateSelf(endDegree, targetEndDegree, velocity);
this.sweepDegree = endDegree - startDegree;
}

String getPercentStr(){
float percent = sweepDegree / 360 * 100;
return String.valueOf((int)percent) + "%";
}

public int getColor(){ return color; }

public String getTitle(){
return title;
}

public float getSweep(){
return sweepDegree;
}

public float getStartDegree(){
return startDegree;
}

public float getEndDegree(){
return endDegree;
}

private float updateSelf(float origin, float target, int velocity){
if (origin < target) {
origin += velocity;
} else if (origin > target){
origin-= velocity;
}
if(Math.abs(target-origin)<velocity){
origin = target;
}
return origin;
}
}

PieView.java


package com.example.androidpiechart;

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

import java.util.ArrayList;


public class PieView extends View {

public interface OnPieClickListener{
void onPieClick(int index);
}

private Paint cirPaint;
private Paint whiteLinePaint;
private Point pieCenterPoint;
private Paint textPaint;
private RectF cirRect;
private RectF cirSelectedRect;

private int mViewWidth;
private int mViewHeight;
private int margin;
private int pieRadius;

private OnPieClickListener onPieClickListener;

private ArrayList<PieHelper> pieHelperList;
private int selectedIndex = NO_SELECTED_INDEX;

private boolean showPercentLabel = true;
public static final int NO_SELECTED_INDEX = -999;
private final int[] DEFAULT_COLOR_LIST = {Color.parseColor("#33B5E5"),
Color.parseColor("#AA66CC"),
Color.parseColor("#99CC00"),
Color.parseColor("#FFBB33"),
Color.parseColor("#FF4444")};


private Runnable animator = new Runnable() {
@Override
public void run() {
boolean needNewFrame = false;
for(PieHelper pie : pieHelperList){
pie.update();
if(!pie.isAtRest()){
needNewFrame = true;
}
}
if (needNewFrame) {
postDelayed(this, 10);
}
invalidate();
}
};

public PieView(Context context){
this(context,null);
}
public PieView(Context context, AttributeSet attrs){
super(context, attrs);

pieHelperList = new ArrayList<PieHelper>();
cirPaint = new Paint();
cirPaint.setAntiAlias(true);
cirPaint.setColor(Color.GRAY);
whiteLinePaint = new Paint(cirPaint);
whiteLinePaint.setColor(Color.WHITE);
whiteLinePaint.setStrokeWidth(2f);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(MyUtils.sp2px(getContext(), 13));
textPaint.setStrokeWidth(5);
textPaint.setTextAlign(Paint.Align.CENTER);
pieCenterPoint = new Point();
cirRect = new RectF();
cirSelectedRect = new RectF();
}

public void showPercentLabel(boolean show){
showPercentLabel = show;
postInvalidate();
}

public void setOnPieClickListener(OnPieClickListener listener){
onPieClickListener = listener;
}

public void setDate(ArrayList<PieHelper> helperList){
initPies(helperList);
pieHelperList.clear();
removeSelectedPie();

if(helperList != null && !helperList.isEmpty()){
for(PieHelper pieHelper:helperList){
pieHelperList.add(new PieHelper(pieHelper.getStartDegree(),pieHelper.getStartDegree(),pieHelper));
}
}else {
pieHelperList.clear();
}

removeCallbacks(animator);
post(animator);


}


private void initPies(ArrayList<PieHelper> helperList){
float totalAngel = 270;
for(PieHelper pie:helperList){
pie.setDegree(totalAngel, totalAngel + pie.getSweep());
totalAngel += pie.getSweep();
}
}

public void selectedPie(int index){
selectedIndex = index;
if(onPieClickListener!=null) onPieClickListener.onPieClick(index);
postInvalidate();
}

public void removeSelectedPie(){
selectedIndex = NO_SELECTED_INDEX;
if(onPieClickListener!=null) onPieClickListener.onPieClick(NO_SELECTED_INDEX);
postInvalidate();
}

@Override
protected void onDraw(Canvas canvas) {
if(pieHelperList.isEmpty()){
return ;
}

int index = 0;
for(PieHelper pieHelper : pieHelperList){
boolean selected = (selectedIndex == index);
RectF rect = selected? cirSelectedRect: cirRect;
if(pieHelper.isColorSetted()){
cirPaint.setColor(pieHelper.getColor());
}else {
cirPaint.setColor(DEFAULT_COLOR_LIST[index%5]);
}
canvas.drawArc(rect, pieHelper.getStartDegree(), pieHelper.getSweep(), true, cirPaint);
drawPercentText(canvas, pieHelper);

drawLineBesideCir(canvas, pieHelper.getStartDegree(), selected);
drawLineBesideCir(canvas, pieHelper.getEndDegree(), selected);
index++;
}

}

private void drawLineBesideCir(Canvas canvas, float angel, boolean selectedCir){
int sth2 = selectedCir? mViewHeight/2 : pieRadius; // Sorry I'm really don't know how to name the variable..
int sth = 1;                                       // And it's
if(angel%360 > 180 && angel%360 < 360){
sth = -1;
}
float lineToX = (float)(mViewHeight/2 + Math.cos(Math.toRadians(-angel)) * sth2);
float lineToY = (float)(mViewHeight/2 + sth * Math.abs(Math.sin(Math.toRadians(-angel))) * sth2);
canvas.drawLine(pieCenterPoint.x, pieCenterPoint.y, lineToX, lineToY, whiteLinePaint);
}

private void drawPercentText(Canvas canvas, PieHelper pieHelper){
if(!showPercentLabel) return ;
float angel = (pieHelper.getStartDegree() + pieHelper.getEndDegree()) /2;
int sth = 1;
if(angel%360 > 180 && angel%360 < 360){
sth = -1;
}
float x = (float)(mViewHeight/2 + Math.cos(Math.toRadians(-angel)) * pieRadius/2);
float y = (float)(mViewHeight/2 + sth * Math.abs(Math.sin(Math.toRadians(-angel))) * pieRadius/2);
canvas.drawText(pieHelper.getPercentStr(), x, y, textPaint);
}

private void drawText(Canvas canvas, PieHelper pieHelper){
if(pieHelper.getTitle() == null) return ;
float angel = (pieHelper.getStartDegree() + pieHelper.getEndDegree()) /2;
int sth = 1;
if(angel%360 > 180 && angel%360 < 360){
sth = -1;
}
float x = (float)(mViewHeight/2 + Math.cos(Math.toRadians(-angel)) * pieRadius/2);
float y = (float)(mViewHeight/2 + sth * Math.abs(Math.sin(Math.toRadians(-angel))) * pieRadius/2);
canvas.drawText(pieHelper.getTitle(), x, y, textPaint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN ||event.getAction() == MotionEvent.ACTION_MOVE){
selectedIndex = findPointAt((int) event.getX(), (int) event.getY());
if(onPieClickListener != null){
onPieClickListener.onPieClick(selectedIndex);
}
postInvalidate();
}

return true;
}


private int findPointAt(int x, int y){
double degree = Math.atan2(x-pieCenterPoint.x, y-pieCenterPoint.y)* 180 / Math.PI;
degree = -(degree-180) + 270;
int index = 0;
for(PieHelper pieHelper:pieHelperList){
if(degree>=pieHelper.getStartDegree() && degree<=pieHelper.getEndDegree()){
return index;
}
index++;
}
return NO_SELECTED_INDEX;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mViewWidth = measureWidth(widthMeasureSpec);
mViewHeight = measureHeight(heightMeasureSpec);
margin = mViewWidth/16;
pieRadius = (mViewWidth)/2-margin;
pieCenterPoint.set(pieRadius+margin, pieRadius+margin);
cirRect.set(pieCenterPoint.x-pieRadius,
pieCenterPoint.y-pieRadius,
pieCenterPoint.x+pieRadius,
pieCenterPoint.y+pieRadius);
cirSelectedRect.set(2, //minor margin for bigger circle
2,
mViewWidth-2,
mViewHeight-2);
setMeasuredDimension(mViewWidth, mViewHeight);
}

private int measureWidth(int measureSpec){
int preferred = 3;
return getMeasurement(measureSpec, preferred);
}

private int measureHeight(int measureSpec){
int preferred = mViewWidth;
return getMeasurement(measureSpec, preferred);
}

private int getMeasurement(int measureSpec, int preferred){
int specSize = View.MeasureSpec.getSize(measureSpec);
int measurement;

switch(View.MeasureSpec.getMode(measureSpec)){
case View.MeasureSpec.EXACTLY:
measurement = specSize;
break;
case View.MeasureSpec.AT_MOST:
measurement = Math.min(preferred, specSize);
break;
default:
measurement = preferred;
break;
}
return measurement;
}
}

 

admin@androidtrainee

 Previous Article Picasso Image Loader With GridView For Android.
Next Article   Draw Android Line Chart With Animation.

Related Posts

  • Android New Quick Action Animation.

    July 15, 2015
  • Android satellite menu Animation.

    July 15, 2015
  • Android Staggered Grid & List View.

    July 14, 2015

Leave a Reply

Cancel reply

Tags

admob Advertising Networks AerServ Airpush android android ads android Advertising Networks Android App android chart animation Android GridView android L android lollipop androidmapv2 AppBrain AppFlood Appia AppKey Appnext AppOptim Appwiz chart chartview Epom Market google place api GridView Image Loader InMobi LeadBolt location map mapv2 mapv2 api material design Minimob Mobicow MobileCore MobiMicro NativeX Pingjam RevMob StarApplication startapp TapContext touched location Widdit

Count per Day

  • 347Reads yesterday:
  • 463819Total visitors:
  • 39Visitors today:
  • 2412Visitors per month:
  • 0Visitors currently online:
© Copyright 2014. Theme by BloomPixel.
Posting....