Android Custom View Implementation Line chart effect _android

Source: Internet
Author: User
Tags drawtext getcolor polyline

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.

Xinit=interval/2+xori; 

onLayoutthe 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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.