In the previous blog, we have created a line chart. Next we will create a bar chart and a pie chart.
The process of creating a column chart is similar to that of creating a line chart. Only the code is provided below, which is not described in detail.
A pie chart is relatively easy. You only need to calculate the size of each data proportion and rotate it to draw a slice chart. See the following code.
Start
Column chart
Since it was rewritten during the training, the function of the previous blog may be less, please refer to the previous blog:
Package hk. jerry. barchart;
Import java. util. List;
Import android. annotation. SuppressLint;
Import android. content. Context;
Import android. graphics. Canvas;
Import android. graphics. Paint;
Import android. graphics. Paint. Align;
Import android. util. AttributeSet;
Import android. util. Log;
Import android. view. MotionEvent;
Import android. view. View;
@ SuppressLint ("InlinedApi ")
Public class BarChartView extends View {
Private Paint paintAxis;
Private Paint paintBar;
Private Paint paintText;
Private Paint paintClear;
Private int startX;
Private int stopX;
Private int startY;
Private int stopY;
Private int chartWidth;
Private int chartHeight;
Private List dataSets;
Private float max;
Private float min;
Private int levelsX;
Private int levelsY;
Private float spaceX;
Private float spaceY;
Private int offsetLeft = 100;
Private float downX;
Private String title;
Private boolean drew = false;
Private int length = 0;
Private int maxDataSetsLength =-1;
Private boolean scrollabled = true;
Public BarChartView (Context context ){
Super (context );
}
Public BarChartView (Context context, AttributeSet attributeSet ){
Super (context, attributeSet );
}
@ Override
Protected void onDraw (Canvas canvas ){
Super. onDraw (canvas );
SetBackgroundColor (getResources (). getColor (android. R. color. white ));
If (dataSets = null | dataSets. isEmpty ()){
If (drew ){
Canvas. drawRect (0, 0, getWidth (), getHeight (), paintClear );
} Else {
Return;
}
}
Drew = true;
Init ();
// Draw the x axis
Canvas. drawLine (startX, stopY, stopX, stopY, paintAxis );
// Draw the scale and data Coordinates. Only 11 + left and right columns in the field of sight are buffered.
Int j = (int) Math. ceil (0-offsetLeft/spaceX)-1;
For (int I = 0; I <= (levelsX> 11? 11: levelsX) + 1; I ++, j ++ ){
If (j <0 | j> = dataSets. size () {// prevent array subscript from exceeding the bounds
Continue;
}
DataSet dataSet = dataSets. get (j );
Float x = getPositionX (j );
PaintAxis. setTextAlign (Align. CENTER );
Canvas. drawLine (x, stopY, x, stopY + 10, paintAxis );
Canvas. drawText (dataSet. name, x, stopY + 25, paintAxis );
Float y = getPositionY (dataSet. value );
Canvas. drawRect (x-20, y, x + 20, stopY, paintBar );
Canvas. drawText (String. valueOf (dataSet. value), x, y-10, paintBar );
}
Canvas. drawRect (0, 0, startX, getHeight (), paintClear );
Canvas. drawLine (startX, startY, startX, stopY, paintAxis );
For (int I = 0; I <levelsY; I ++ ){
Float y = getPositionY (min + I * 5 );
PaintAxis. setTextAlign (Align. RIGHT );
Canvas. drawLine (startX-10, y, startX, y, paintAxis );
Canvas. drawText (String. valueOf (int) min + I * 5), startX-12, y + 5, paintAxis );
}
If (title! = Null ){
Log. d ("test", title );
Canvas. drawText (title, getWidth ()/2, 0 + 50, paintText );
}
}
Private void init (){
PaintAxis = new Paint ();
PaintAxis. setStrokeWidth (3 );
PaintAxis. setAntiAlias (true );
PaintAxis. setTextSize (16 );
PaintAxis. setColor (getResources (). getColor (android. R. color. secondary_text_dark ));
PaintBar = new Paint ();
PaintBar. setStrokeWidth (3 );
PaintBar. setAntiAlias (true );
PaintBar. setTextSize (20 );
PaintBar. setColor (getResources (). getColor (android. R. color. holo_green_dark ));
PaintBar. setTextAlign (Align. CENTER );
PaintText = new Paint ();
PaintText. setAntiAlias (true );
PaintText. setTextSize (35 );
PaintText. setTextAlign (Align. CENTER );
PaintText. setColor (getResources (). getColor (android. R. color. holo_green_dark ));
PaintClear = new Paint ();
PaintClear. setColor (getResources (). getColor (android. R. color. white ));
StartX = 50;
StopX = getWidth ();
StartY = 80;
StopY = getHeight ()-50;
ChartHeight = stopY-startY;
ChartWidth = stopX-startX;
Max = min = dataSets. get (0). value;
For (int I = 0; I <dataSets. size (); I ++) {DataSet dataSet = dataSets. get (I); if (dataSet. value> max ){
Max = dataSet. value;
}
If (dataSet. value <min) {min = dataSet. value ;}} levelsX = dataSets. size () + 1; levelsY = (int) Math. ceil (max-min)/5) + 1; spaceY = chartHeight/levelsY; spaceX = levelsX> 10? ChartWidth/11: chartWidth/(levelsX + 1 );
Length = (int) (dataSets. size () * spaceX );
}
Private float getPositionX (int X ){
Return spaceX * X + offsetLeft;
}
Private float getPositionY (float value ){
Int exceedNum = (int) Math. floor (value-min)/5) + 1;
Return (float) stopY)-spaceY * exceedNum-(value-min) % 5/5) * spaceY;
}
Public void empty (){
DataSets = null;
Title = null;
Length = 0;
Invalidate ();
}
Public void setDataSets (List dataSets ){
Length = 0;
This. dataSets = dataSets;
Invalidate ();
}
/*
* Add a dataset
*/
Public void addDataSet (DataSet dataSet ){
If (maxDataSetsLength! =-1 & dataSets. size ()> maxDataSetsLength ){
DataSets. remove (0 );
}
DataSets. add (dataSet );
ScrollToEnd ();
}
Public void setMaxDataSetsLength (int maxDataSetsLength ){
This. maxDataSetsLength = maxDataSetsLength;
}
Public void setScrollable (boolean scrollabled ){
This. scrollabled = scrollabled;
}
Public void setTitle (String title ){
This. title = title;
Invalidate ();
}
Public void scrollToStart (){
If (! Drew ){
Invalidate ();
}
OffsetLeft = 100;
Invalidate ();
}
Public void scrollToEnd (){
If (! Drew ){
Invalidate ();
}
OffsetLeft = chartWidth> = length? 100: (0-(length-chartWidth)-100 );
Invalidate ();
}
Public boolean isScrolledToStart (){
Return offsetLeft> = 100;
}
Public boolean isScrolledToEnd (){
Return chartWidth> = length? (OffsetLeft <= 100): (offsetLeft <0-(length-chartWidth ));
}
@ SuppressLint ("ClickableViewAccessibility ")
@ Override
Public boolean onTouchEvent (MotionEvent event ){
Switch (event. getAction ()){
Case MotionEvent. ACTION_DOWN:
DownX = event. getRawX ();
Break;
Case MotionEvent. ACTION_MOVE:
If (! Scrollabled ){
Return true;
}
OffsetLeft + = event. getRawX ()-downX;
DownX = event. getRawX ();
If (isScrolledToStart ()){
ScrollToStart ();
} Else if (isScrolledToEnd ()){
ScrollToEnd ();
} Else {
Invalidate ();
}
Break;
}
Return true;
}
Public static class DataSet {
Public String name;
Public float value;
Public DataSet (String name, float value ){
This. name = name;
This. value = value;
}
}
}
The test code is the same, so I will not post it here.
Pie chart
Control code:
Package hk. jerry. piechart;
Import java. util. List;
Import java. util. Random;
Import android. annotation. SuppressLint;
Import android. content. Context;
Import android. graphics. BlurMaskFilter;
Import android. graphics. Canvas;
Import android. graphics. Paint;
Import android. graphics. Path;
Import android. graphics. Path. Direction;
Import android. graphics. RectF;
Import android. util. AttributeSet;
Import android. view. View;
@ SuppressLint ({"NewApi", "DrawAllocation "})
Public class PieChartView extends View {
Private Paint paintStroke = new Paint (Paint. ANTI_ALIAS_FLAG); // Click the pie chart outline
Private Paint paintPie = new Paint (Paint. ANTI_ALIAS_FLAG); // slice painter
Private Paint paintText = new Paint (Paint. ANTI_ALIAS_FLAG); // use a pie chart
Private float startX, stopX, startY, stopY; // the start position and end position of the pie chart.
Private float cx, cy, radius; // center X, Y, radius
Private float sum; // The sum of data.
Private List dataSets; // dataset
Private Random random = new Random (); // Random class
Private String title; // the title.
Public PieChartView (Context context ){
Super (context );
}
Public PieChartView (Context context, AttributeSet attrs ){
Super (context, attrs );
}
Public void init (){
// Set the pie chart contour painter parameters
BlurMaskFilter filter = new BlurMaskFilter (1, BlurMaskFilter. Blur. INNER );
PaintStroke. setARGB (255,155,155,155 );
PaintStroke. setStrokeWidth (4 );
PaintStroke. setStyle (Paint. Style. STROKE );
PaintStroke. setMaskFilter (filter );
// Set the parameter of the pie chart sector painter
PaintPie. setStyle (Paint. Style. FILL );
PaintPie. setMaskFilter (filter );
PaintPie. setTextSize (25 );
// Set the flat parameters
PaintText. setTextSize (35 );
// Calculate the start and end positions of the pie chart. To ensure that the pie chart is a positive circle, the left and right sides must be consistent with the upper and lower width.
StartX = 10;
StartY = 100;
StopX = stopY = (getHeight () <getWidth ()? GetHeight (): getWidth ()-50;
// Calculates the coordinates of the center according to the start and end positions
Cx = (stopX-startX)/2 + startX;
Cy = (stopY-startY)/2 + startY;
// Calculate the radius
Radius = (stopX-startX)/2;
// Traverse the dataset to calculate the sum
Sum = 0;
For (int I = 0; I <dataSets. size (); I ++ ){
Sum + = dataSets. get (I). value;
}
}
@ Override
Protected void onDraw (Canvas canvas ){
Super. onDraw (canvas );
Init ();
// Generate the Path and draw the outline of the pie chart
Path path = new Path ();
Path. addCircle (cx, cy, radius, Direction. CW );
Canvas. drawPath (path, paintStroke );
// Generate RectF for subsequent sector drawing
RectF rectF = new RectF (cx-radius, cy-radius, cx + radius, cy + radius );
// Sector offset angle
Float startAngle = 0;
// Pie chart data flag offset value
Float offset = 30;
For (int I = 0; I <dataSets. size (); I ++ ){
DataSet dataSet = dataSets. get (I );
Float percentage = dataSet. value/sum * 360; // calculates the percentage to get the angle
PaintPie. setARGB (255, random. nextInt (255), random. nextInt (255), random. nextInt (255); // randomly generated color
Canvas. drawArc (rectF, startAngle, percentage, true, paintPie); // draw slices
StartAngle + = percentage; // add the angle just calculated to the offset angle as the offset angle of the next sector for easy plotting
Canvas. drawRect (stopX + 60, startY + offset, stopX + 100, startY + offset + 30, paintPie); // draw a data flag
Canvas. drawText (dataSet. name + "(" + (dataSet. value/sum * 100) + "%)", stopX + 130, startY + offset + 23, paintPie); // plot the data value
Offset + = 50;
}
If (title! = Null) {// draw the title
Canvas. drawText (title, getWidth ()/2, 50, paintText );
}
}
Public void setTitle (String title ){
This. title = title;
}
Public void setDataSets (List dataSets ){
This. dataSets = dataSets;
Invalidate ();
}
Public void addDataSet (DataSet dataSet ){
DataSets. add (dataSet );
Invalidate ();
}
Public static class DataSet {
Public String name;
Public float value;
Public DataSet (String name, float value ){
This. name = name;
This. value = value;
}
}
}
The layout code is no longer available. Similar to the previous blog post, you can directly test the code:
Final PieChartView pc = (PieChartView) findViewById (R. id. pc_test );
Pc. setTitle ("test chart ");
Random random = new Random ();
List dataSets = new ArrayList ();
For (int I = 0; I <= 5; I ++ ){
Float value = random. nextInt (50 );
DataSets. add (new DataSet ("number" + (I + 1) + "data", value ));
}
Pc. setDataSets (dataSets );
BtnAdd. setOnClickListener (new OnClickListener (){
@ Override
Public void onClick (View v ){
Pc. addDataSet (new DataSet (etName. getText (). toString (), Float. valueOf (etValue. getText (). toString ())));
}
});
Running effect