Here is the result chart (each state is represented by an emoticon):
One, the main page layout file is as follows:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent "
tools:context= ". Mainactivity "
xmlns:app=" Http://schemas.android.com/apk/res/ting.example.linecharview ">
< Ting.example.linecharview.LineCharView
android:id= "@+id/test"
android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
app:xytextcolor= "@color/bg"
app:xytextsize= "20SP"
app: Interval= "80DP"
/>
It's a linecharview
custom View
, and it's a app:xx
View
variety of attributes.
In values
the Attrs file, add the following XML to define linecharview
the various attributes:
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<declare-styleable name= "Linechar" >
<attr name= "xylinecolor" format= "color"/><!--xy axis color--> <attr "name=" Xylinewidth "
Dimension "/><!--xy axis width--> <attr name=" Xytextcolor "format=
" color "/><!--xy axis text color-->
<attr name= "xytextsize" format= "Dimension"/><!--xy axis text size--> <attr name=
"linecolor" format = "Color"/><!--the colors of a polyline in a line chart--> <attr name= "Interval" format= "Dimension"/><
!--horizontal spacing for each coordinate point of the x-axis-->
<attr name= "bgcolor" format= "color"/><!--background color-->
</declare-styleable>
Next, we build a class LineCharView
inheritance and View
declare the following variables:
<span style= "White-space:pre" > </span>private int xori;//dot x coordinate
private int yori;//dot y coordinate
private int xinit;//First point x coordinate
private int minxinit;//When moving, the first point allows the smallest x coordinates to
be private int maxxinit;//when moving, the first point allows maximum x coordinates to be allowed
private int Xylinecolor;//xy axis color
private int xylinewidth;//xy axis size
private int xytextcolor;//xy axis text color
private int Xytextsize;//xy axis text size
private int linecolor;//polyline color
private int interval;//coordinate interval
private int bgcolor;//background color
private list<string> x_coords;//x coordinate point value
private list<string> X_coord _values;//each point state value
private int width;//control width
private int heigth;//control height
private int imagewidth;//expression width
Private Float textwidth;//y axis text width
To read individual property values in the constructor:
Linecharview (context, AttributeSet attrs) {Super (context, attrs);
TypedArray typedarray= context.obtainstyledattributes (attrs, R.styleable.linechar);
Xylinecolor=typedarray.getcolor (R.styleable.linechar_xylinecolor, Color.gray);
Xylinewidth=typedarray.getint (R.styleable.linechar_xylinewidth, 5);
Xytextcolor=typedarray.getcolor (R.styleable.linechar_xytextcolor, Color.Black);
Xytextsize=typedarray.getlayoutdimension (R.styleable.linechar_xytextsize, 20);
Linecolor=typedarray.getcolor (R.styleable.linechar_linecolor, Color.gray);
Interval=typedarray.getlayoutdimension (R.styleable.linechar_interval, 100);
Bgcolor=typedarray.getcolor (R.styleable.linechar_bgcolor, Color.White);
Typedarray.recycle ();
X_coords=new arraylist<string> ();
X_coord_values=new arraylist<string> (); }
Next, you can rewrite onLayout
the method, to calculate the width of the control and the origin coordinates of the axes, the x-coordinate of the Axis origin can be computed by the width of the y-axis text, the y-axis width, and the horizontal distance from Y, where the y-axis text has only 4 states (A, B, C, D), You can use the following method to calculate the x-coordinate of the origin:
Paint paint=new Paint ();
Paint.settextsize (xytextsize);
Textwidth= paint.measuretext ("A");
The y-coordinate of the origin can also be computed in a similar way:
When the amount of data that needs to be displayed is multiple, can not show all time, need to show through the slide line chart, we only need to control the 1th x coordinate, we can calculate the coordinates of each point by interval this property, but in order to prevent all the data slide out of the interface, need to control when sliding In fact, control the first point of the x-coordinate range, the first point of the X coordinates of the minimum value can be the width of the control minus the origin x coordinates minus the horizontal distance of all line charts, the code is as follows:
Control at the default first display, the first point is half the horizontal distance from the y-axis, and interval
if the first point appears in this position at the time of the slide, it is not allowed to continue to slide to the right, so the maximum value of the first point x coordinates is equal to the starting X coordinate.
onLayout
the code for overriding the method is as follows:
@Override
protected void OnLayout (Boolean changed, int left, int. top, int right,
int bottom) {
if (changed) {
width=getwidth ();
Heigth=getheight ();
Paint paint=new Paint ();
Paint.settextsize (xytextsize);
Textwidth= paint.measuretext ("A");
xori= (int) (textwidth+6+2*xylinewidth);//6 is
yori=heigth-xytextsize-2*xylinewidth-3;//3 to x-axis
intervals from the y-axis Xinit=interval/2+xori;
Imagewidth= Bitmapfactory.decoderesource (Getresources (), R.drawable.facea). GetWidth ();
Minxinit=width-xori-x_coords.size () *interval;
Maxxinit=xinit;
SetBackgroundColor (bgcolor);
}
Super.onlayout (changed, left, top, right, bottom);
Next you can draw a polyline, a small dot on the x axis, and a line expression.
The code is as follows:
Draw x-axis coordinates, polylines, emoticons @SuppressLint ("Resourceascolor") private void Drawx (Canvas Canvas) {Paint x_coordpaint =new Paint (
);
X_coordpaint.settextsize (xytextsize);
X_coordpaint.setstyle (Paint.Style.FILL);
Path path=new path ();
Draw the small Origin point on the axis, the axis text for (int i=0;i<x_coords.size (); i++) {int x=i*interval+xinit;
if (i==0) {Path.moveto (x, Getyvalue (X_coord_values.get (i)));
}else{Path.lineto (x, Getyvalue (X_coord_values.get (i)));
} x_coordpaint.setcolor (Xylinecolor);
Canvas.drawcircle (x, Yori, xylinewidth*2, X_coordpaint);
String Text=x_coords.get (i);
X_coordpaint.setcolor (Xytextcolor);
Canvas.drawtext (text, X-x_coordpaint.measuretext (text)/2, yori+xytextsize+xylinewidth*2, x_coordpaint);
} x_coordpaint.setstyle (Paint.Style.STROKE);
X_coordpaint.setstrokewidth (Xylinewidth);
X_coordpaint.setcolor (LineColor);
Draw a polyline Canvas.drawpath (path, x_coordpaint);
Picture expression for (int i=0;i<x_coords.size (); i++) {int x=i*interval+xinit; Canvas.drawbitmap (GetYBitmap (X_coord_values.get (i)), X-IMAGEWIDTH/2, Getyvalue (X_coord_values.get (i))-IMAGEWIDTH/2, x_coordpaint);
(//) intercept the X_coordpaint.setstyle (Paint.Style.FILL) by cutting the polyline beyond the x-axis coordinates;
X_coordpaint.setcolor (bgcolor);
X_coordpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_OVER));
RECTF rectf=new RECTF (0, 0, Xori, heigth);
Canvas.drawrect (RECTF, x_coordpaint); }
The above code first draws a coordinate point, polyline, expression by traversing the two list collection of x_coords
and x_coord_values
, because it is possible to move the coordinate points when you slide to the left. The polyline is drawn to the left of the y-axis, so it needs to be intercepted. where getyvalue
and the Getybitmap method, you can calculate the y-coordinate and the corresponding expression by the value of x_coord_values
. Two methods, such as:
//get y-coordinate private float getyvalue (String value) {if (Value.equalsignorecase ("A")) {
return YORI-INTERVAL/2;
else if (value.equalsignorecase ("B")) {return yori-interval;
else if (value.equalsignorecase ("C")) {return (float) (yori-interval*1.5);
else if (value.equalsignorecase ("D")) {return yori-interval*2;
}else{return yori;
}///Get Emoticons private Bitmap Getybitmap (String value) {Bitmap bitmap=null;
if (Value.equalsignorecase ("A")) {Bitmap=bitmapfactory.decoderesource (Getresources (), r.drawable.facea);
else if (value.equalsignorecase ("B")) {Bitmap=bitmapfactory.decoderesource (Getresources (), R.DRAWABLE.FACEB);
else if (value.equalsignorecase ("C")) {Bitmap=bitmapfactory.decoderesource (Getresources (), R.DRAWABLE.FACEC);
else if (value.equalsignorecase ("D")) {Bitmap=bitmapfactory.decoderesource (Getresources (), r.drawable.faced);
return bitmap; }
Six, draw a coordinate point, polyline, expression, and then simple, you can draw x y axis, x y axis as long as the original point of the coordinates, it is very simple, the code is as follows:
Draw axis
private void Drawxy (Canvas Canvas) {
Paint paint=new Paint ();
Paint.setcolor (Xylinecolor);
Paint.setstrokewidth (xylinewidth);
Canvas.drawline (Xori, 0, Xori, yori, paint);
Canvas.drawline (Xori, Yori, Width, yori, paint);
In the end, you can draw the coordinates on the y-axis and the text on the Y axis:
Draw the y-axis coordinate point
private void Drawy (Canvas Canvas) {
Paint paint=new Paint ();
Paint.setcolor (Xylinecolor);
Paint.setstyle (Paint.Style.FILL);
for (int i=1;i<5; i++) {
canvas.drawcircle (Xori, yori-(I*INTERVAL/2), xylinewidth*2, paint);
Paint.settextsize (xytextsize);
Paint.setcolor (Xytextcolor);
Canvas.drawtext ("D", Xori-textwidth-6-xylinewidth, yori-(2*interval) +XYTEXTSIZE/2, paint);
Canvas.drawtext ("C", Xori-textwidth-6-xylinewidth, (float) (yori-(1.5*interval) +XYTEXTSIZE/2), paint);
Canvas.drawtext ("B", Xori-textwidth-6-xylinewidth, YORI-INTERVAL+XYTEXTSIZE/2, paint);
Canvas.drawtext ("A", Xori-textwidth-6-xylinewidth, (float) (yori-(0.5*interval) +XYTEXTSIZE/2), paint);
Eight, wrote over the above three methods: just need to rewrite the onDraw
method, you can draw.
@Override
protected void OnDraw (Canvas Canvas) {
drawx (Canvas);
Drawxy (canvas);
Drawy (canvas);
Nine, in order to be able to slide horizontally, you need to rewrite the control of the Ontouchevent method, in the sliding, real-time calculation of the finger sliding distance to change the first point of the X coordinate, and then call invalidate();
can refresh the control, redraw to achieve sliding effect.
@Override Public
Boolean ontouchevent (Motionevent event) {
//If you can display all the data without sliding, do not let slip
if (interval*x_coord _values.size () <=width-xori) {return
false;
}
Switch (event.getaction ()) {case
Motionevent.action_down:
startx=event.getx ();
break;
Case Motionevent.action_move:
float dis=event.getx ()-startx;
Startx=event.getx ();
if (xinit+dis>maxxinit) {
xinit=maxxinit;
} else if (xinit+dis<minxinit) {
xinit=minxinit
} else{
xinit= (int) (Xinit+dis);
}
Invalidate ();
break;
return true;
Finally, add a method to set up the data source, set x_coords
, x_coord_values
This two List
collection, after the setup is complete, call invalidate()
to refresh the control:
/**
* Set coordinate line chart value
* @param x_coords coordinate point
* @param x_coord_values The value of each point
/public void SetValue (list& Lt string> x_coords,list<string> x_coord_values) {
if (x_coord_values.size ()!=x_coords.size ()) {
throw new IllegalArgumentException (the number of values must be the same for axis and axis points!);
}
This.x_coord_values=x_coord_values;
This.x_coords=x_coords;
Invalidate ();
Summarize
This is the Android custom view to achieve the full line chart effect, I hope to develop Android can help.