Android Developer's Custom view feature (i): Custom Column Chart

Source: Internet
Author: User
Tags dashed line drawtext gety

Bo Master before the project, need to use the report function, before the online Baidu Google a variety of results, no one is able to meet the needs of bloggers boss, but before Bo Master had to study. Finally, a good result has been worked out. First on:

This is a report of a blogger's project. Boss request can click on the left side of the month to compare the month, you can also click to select the month, the right column chart bar is able to respond to click events, and can slide the month to switch, if the column chart content too long beyond the interface, you can also swipe left and right to view the content is not displayed. Here only the column chart generation, the other interface effect Bo Master will not explain. The actual effect and such a little difference, but not big, mainly the actual effect at the top of the column chart will also display values.

Custom column charts are available in two ways that can be written in an XML file or added to a container after new in the code. Bloggers are not described in detail here, it took the blogger 1 hours to separate the view from the project. Interested students can download the complete project down to study.

Github:https://github.com/victorfreedom1989/freedomhistogram

csdn:http://download.csdn.net/detail/victorfreedom/8309505



1, custom Column chart The first step, custom bar bar:

Package Com.freedom.histogram;import Java.text.decimalformat;import Android.content.context;import Android.graphics.canvas;import android.graphics.color;import android.graphics.paint;/** * @ClassName: Freedomhistogram * @author victor_freedom ([email protected]) * @createddate 2014-12-28 PM 10:44:52 * @Description: * /public class Freedomhistogram {//bar width private int with;//column height private int height;//bar corresponding value private double count;//start y sit private int axisy;//header start y coordinate private int titley;//bar start x coordinate private int axisx;private Context context;private Decimalforma T df;private Paint mpaint;public Freedomhistogram (context context, int with, float axisy) {this.with = With;this.axisy = S CREENUTIL.DIP2PX (context, axisy); This.titley = screenutil.dip2px (context, Axisy +); this.context = CONTEXT;THIS.DF = New DecimalFormat ("#0.0"); mpaint = new Paint (); Mpaint.setantialias (true); Mpaint.setcolor (Color.White);} Public Freedomhistogram () {};p ublic int getaxisx () {return axisX;} public void Setaxisx (int AxisX) {this.axisx = AxisX;} public int getheight () {return height;} public void setheight (int height) {this.height = height;} Public double GetCount () {return count;} public void SetCount (double count) {This.count = count;}  public void Drawhistogram (canvas canvas, paint paint) {//Draw first layer Canvas.drawrect (AxisX-1, axisy-height-1, with + AxisX + 1, axisy,mpaint);//Draw the second layer, let the bar has white edge, good-looking, according to personal preferences can not draw the second layer. Canvas.drawrect (AxisX, axisy-height, with + AxisX, axisY-1, paint);//Draw a column corresponding to the value Canvas.drawtext (Df.format (count), axis X-SCREENUTIL.DIP2PX (context, 5), axisy-height-10,paint);} public void Drawtitle (canvas canvas, paint paint, String name) {//Draw title Canvas.drawrect (AxisX, titley-height, with + axis X, titleY-1, paint); Canvas.drawtext (name, with + AxisX + screenutil.dip2px (context, 5), titleY-1, Paint);}}
2. Custom Column Chart Step two: Building a column chart

Package Com.freedom.histogram;import Java.util.arraylist;import Java.util.list;import java.util.Map;import Android.annotation.suppresslint;import Android.content.context;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.color;import Android.graphics.dashpatheffect;import Android.graphics.paint;import Android.graphics.paint.style;import Android.graphics.patheffect;import Android.graphics.pointf;import Android.graphics.rect;import Android.util.attributeset;import Android.util.floatmath;import android.view.motionevent;import android.view.view;/** * @ClassName: Freedomhistogramview * @author victor_freedom ([email protected]) * @createddate 2014-12-28 10:47:33 * @ Description:todo */public class Freedomhistogramview extends View {private Histogramonclicklistener histogramonclicklistener;public void Sethistogramonclicklistener (Histogramonclicklistener listner) { This.histogramonclicklistener = Listner;} Column chart total data private Map<integer, double[]> datas;//Column Chart each group of data private double[] perdata;//maximum private double max;//draw value private double average;//data How many sets of set private a Rraylist<integer> datakeys;//set of data for each group private arraylist<double[]> valuese;//each group of data corresponding to the region private ArrayList <Rect> rects;//Data How many sets of private int flag;//average line value private double avergerline;//each group of data corresponding to the color private int[] colors = new int [] {0xff8b008b, 0xff00bfff, 0xff4800ff,0xff333333, 0xff006400, 0xff668b8b, 0xffff83fa, 0xff363636,0xff000080, 0xff008b8b, 0XFFFFDAB9, 0xff90ee90};//column chart title corresponding to the value of the private int margin;//column bar private Freedomhistogram Freedomhistogram; Private paint paint;//Whether the lower-left corner draws the caption private Boolean istitle = False;private String title[];//The x-axis coordinates of each set of data bar for the private list&lt ; string> nodes;//column width private int charwith;//column spacing (with margin use) private int withx;//y week corresponds to the number of coordinate points private int numbery;//Y The distance between coordinates points of the axis private float withy;public Freedomhistogramview (context context, AttributeSet Attrs,int Defstyle) {super ( Context, attrs, Defstyle);} /** * title:description: In XMLBuild method in File * * @param context * @param attrs */public Freedomhistogramview (context context, AttributeSet Attrs) {Super (cont ext, attrs); TypedArray a = context.obtainstyledattributes (Attrs,r.styleable.freedomhistogramview); charwith = A.getInteger ( R.styleable.freedomhistogramview_charwith, withx = A.getinteger (R.styleable.freedomhistogramview_withx, 20); Numbery = A.getinteger (r.styleable.freedomhistogramview_numbery); withy = A.getfloat ( R.styleable.freedomhistogramview_withy, Istitle = A.getboolean (R.styleable.freedomhistogramview_istitle, False );p aint = new paint ();p Aint.setantialias (TRUE);//Xpaint.setantialias (TRUE);//Create a new bar Freedomhistogram = new Freedomhistogram (Context, screenutil.dip2px (context, Charwith), Withy * (numberY-1) +); a.recycle (); Public Freedomhistogramview (Context context) {super (context);} Public Freedomhistogramview (context context, Map<integer, double[]> datas,int charwith, int withx, list<string > nodes, int numbery,float withy, Boolean isTitle) {super (context); margin = 0;this.datas = Datas;this.withx = Withx;this.nodes = Nodes;this.numbery = Numbery;this.wi ThY = Withy;this.charwith = Charwith;this.istitle = Istitle;paint = new Paint ();p Aint.setantialias (TRUE);// Xpaint.setantialias (TRUE);//Create a new column bar Freedomhistogram = new Freedomhistogram (context, screenutil.dip2px (context, Charwith), Withy * (numberY-1) + 10);} Public Map<integer, Double[]> Getdatas () {return datas;} Public string[] GetTitle () {return title;} public void Settitle (string[] title) {this.title = title;} public void Setdatas (Map<integer, double[]> datas) {This.datas = datas;//invalidate ();} public Boolean istitle () {return istitle;} public void Settitle (Boolean istitle) {this.istitle = Istitle;} Public list<string> Getnodes () {return nodes;} public void Setnodes (list<string> nodes) {this.nodes = nodes;//invalidate ();} public int Getcharwith () {return charwith;} public void Setcharwith (int charwith) {this.charwith = Charwith;} public int GetWithx () {return withx;} public void setwithx (int withx) {this.withx = Withx;} public float Getnumbery () {return numbery;} public void setnumbery (int numbery) {this.numbery = Numbery;} public float Getwithy () {return withy;} public void Setwithy (float withy) {this.withy = Withy;} public void Inidata () {//Take out numeric integer k;double[] V;datakeys = new arraylist<integer> (); Valuese = new Arraylist<do Uble[]> (); for (Map.entry<integer, double[]> entry:datas.entrySet ()) {k = Entry.getkey ();//Keydatakeys.add (k ); v = Entry.getvalue (); Valuevaluese.add (v);} This.flag = Datakeys.size ();d ouble total = 0;int sum = 0;for (double[] datamax:valuese) {max = Datamax[0];for (double da Ta:datamax) {Total + = Data;max = max > data? max:data;if (Data! = 0.0) {sum++;}}} max = DataChange (max); average = max/(numberY-1); avergerline = Total/sum;} Private double DataChange (double data) {StringBuilder SB = new StringBuilder (); String datastring = string.valueof (data); String Dateint = DatastrinG.substring (0, Datastring.lastindexof (".")); int length = Dateint.length ();  String Newdatafirst = datastring.substring (0, 1), if (Newdatafirst.equals ("9")) {Boolean ischange = false;for (int i = 1; i < Datastring.length (); i++) {String dataper = datastring.substring (i, i + 1), if (Dataper.equals ("0")) {continue;} else {ischange = true;}} if (ischange) {sb.append ("1"), for (int i = 0; i < length; i++) {Sb.append ("0");} Return double.valueof (Sb.tostring ());} else {return data;}} else {Boolean ischange = false;for (int i = 1; i < datastring.length (); i++) {String dataper = datastring.substring (i, i + 1), if (Dataper.equals ("0")) {continue;} else {ischange = True;break;}} if (ischange) {Newdatafirst = (integer.valueof (newdatafirst) + 1) + ""; Sb.append (Newdatafirst); for (int i = 0; i < length-1; i++) {sb.append ("0");} Return double.valueof (Sb.tostring ());} else {return data;}}} public void Drawaxis (canvas canvas) {paint.setcolor (Color.dkgray);p aint.setstrokewidth (screenutil.dip2px (GetconText (), 2));p aint.settextsize (screenutil.sp2px (GetContext ()); Canvas.drawline (screenutil.dip2px () , (), screenutil.dip2px (GetContext (), Withy * (numberY-1) +), screenutil.dip2px (GetContext (), (Withx + (flag-1) * CH Arwith) * (Nodes.size () + 1), screenutil.dip2px (GetContext (), Withy * (numberY-1) +), paint); Canvas.drawline ( SCREENUTIL.DIP2PX (GetContext (), Wuyi), screenutil.dip2px (GetContext (), 5), screenutil.dip2px (GetContext (), 51), SCREENUTIL.DIP2PX (GetContext (), Withy * (numberY-1) +), paint), int x = screenutil.dip2px (GetContext (), (float) (+ f) Lag * charwith/2)); int y = screenutil.dip2px (GetContext (), Withy * (numberY-1) +); for (int i = 0; i < nodes.size ( ); i++) {Canvas.drawtext (Nodes.get (i), x,screenutil.dip2px (GetContext (), Withy * (numberY-1) +), paint); x + = SCREENUTIL.DIP2PX (GetContext (), Withx + (flag-1) * charwith);} for (int i = 0; i < numbery; i++) {Canvas.drawtext (Average.intvalue () * i + "", screenutil.dip2px (GetContext (), 3), Y, p Aint; y-= screenutil.dip2px (GetContext (), withy);}} public void Drawchart (canvas canvas) {rects = new arraylist<rect> (); Rects.clear ();p aint.settextsize ( SCREENUTIL.SP2PX (GetContext (), 8)); for (int j = 0; J < Flag; J + +) {Paint.setcolor (colors[j]);//Paint.setstyle (STYLE.F Ill_and_stroke);//Paint.setstrokewidth (1);p erdata = Valuese.get (j); int temp_screen = screenutil.dip2px (GetContext () , + J * charwith); for (int i = 0; i < perdata.length; i++) {Freedomhistogram.setcount (perdata[i]); FREEDOMHISTOGRAM.S Etheight (screenutil.dip2px (GetContext (), (int) (Perdata[i].intvalue ()/Max * (withy* (numberY-1) +))), if (margin = = 0) {FREEDOMHISTOGRAM.SETAXISX (temp_screen);} else {temp_screen + = screenutil.dip2px (GetContext (), withx+ (flag-1) * Cha Rwith); Freedomhistogram.setaxisx (Temp_screen);} Freedomhistogram.drawhistogram (canvas, paint), margin = screenutil.dip2px (GetContext (), 10); Rect r = new Rect (temp_screen-screenutil.dip2px (GetContext (), (Withx-charwith)/3), screenutil.dip2px (getContext (), Withy * (numberY-1))-screenutil.dip2px (GetContext (), (int) (Perdata[i].intvalue ()/max* withy * (numberY-1 )), temp_screen+ screenutil.dip2px (GetContext (), Charwith) + screenutil.dip2px (GetContext (), (Withx-charwith)/3), SCREENUTIL.DIP2PX (GetContext (), Withy * (numberY-1))); Rects.add (r);} margin = 0;}} public void DrawLine (canvas canvas) {//Dashed line//Paint p = new paint (Paint.anti_alias_flag); Paint Xpaint = new paint (Paint.anti_alias_flag); Xpaint.setantialias (true); Xpaint.setstyle (Style.stroke); Xpaint.setcolor (color.red); Xpaint.setstrokewidth (2); Patheffect effects = new Dashpatheffect (new float[] {screenutil.dip2px (GetContext (), 5), screenutil.dip2px (GetContext ( ), 5), screenutil.dip2px (GetContext (), 5), screenutil.dip2px (GetContext (), 5)}, 1); Xpaint.setpatheffect (effects); Canvas.drawline (screenutil.dip2px (GetContext (), Wuyi), screenutil.dip2px (GetContext (), withy* (numberY-1) + 10-(int) ( Avergerline/max * (withy* (numberY-1) +)), screenutil.dip2px (GetContext (), (Withx + (flag-1) * charwith) * (Nodes.size () + 1)), screenutil.dip2px (GetContext (), withy* (numberY-1) + 10-(int) (Avergerline /Max * (withy* (numberY-1))), xpaint);} public void Drawtitle (canvas canvas) {paint.settextsize (screenutil.sp2px (GetContext (), n)); int title_screen = SCREENUTIL.DIP2PX (GetContext (), charwith); for (int i = 0; i < datakeys.size (); i++) {Paint.setcolor (colors[i]); Freedomhistogram.setheight (screenutil.dip2px (GetContext ())), if (margin = = 0) {FREEDOMHISTOGRAM.SETAXISX (title_ screen+ screenutil.dip2px (GetContext (), + margin);} else {FREEDOMHISTOGRAM.SETAXISX (title_screen+ screenutil.dip2px (GetContext (), +) + margin);} Freedomhistogram.drawtitle (canvas, Paint, title[i]), margin = screenutil.dip2px (GetContext (), title_screen); Freedomhistogram.getaxisx ();} margin = 0;} /** * need to get the width and height of the control */@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure ( Widthmeasurespec, Heightmeasurespec);//Set the width and height of the switch for the background image of the wide height SetmeasureddimensiOn (screenutil.dip2px (GetContext (), + (WITHX + flag * charwith) * (Nodes.size () + 1)), screenutil.dip2px (GetContext (), WI ThY * numbery + 50));} @Overridepublic void OnDraw (canvas canvas) {canvas.drawcolor (color.transparent); Inidata ();d rawchart (canvas); Drawaxis (Canvas), if (flag = = 1) {drawline (canvas);} if (istitle) {drawtitle (canvas);} Super.ondraw (canvas);}  Private float Scale;private float lastscale;private Boolean firsttouch = true;private Boolean guide = True;private boolean move = false;private int mode = 0;private int DRAG = 1;private int ZOOM = 2;private float startdis;int x1 = 0;int y1 = 0; private int startX = 0; @Overridepublic boolean ontouchevent (Motionevent event) {switch (Event.getaction () & Motioneve Nt. Action_mask) {Case MotionEvent.ACTION_DOWN:mode = DRAG;STARTX = (int) event.getrawx (), scale = This.getscalex (); move = FAL Se;break;case MotionEvent.ACTION_MOVE:if (mode = = DRAG) {int newx = (int) event.getrawx (); int dx = newx-startx;if (dx &G T {move = true;} int L = ThiS.getleft () + dx;int t = this.gettop (); int r = this.getright () + dx;int B = This.getbottom (); This.layout (L, T, R, b); start X = (int) event.getrawx ();} else if (mode = = ZOOM) {Float Enddis = distance (event); if (Enddis > 10f) {lastscale = Scale;scale = Enddis/startdis;i F (Firsttouch) {if (Scale > Lastscale) {guide = true;} else {guide = false;} Firsttouch = false;} if (guide) {if (Scale < Lastscale) {scale = Lastscale,}} else {if (Scale > Lastscale) {scale = Lastscale;} Scale = scale * LASTSCALE;IF (Scale < 1) {Lastscale = 1;scale = 1;}}} Break;case MotionEvent.ACTION_UP:if (Scale = = 1 && datakeys.size () = = 1 &&!move) {x1 = (int) event.getx () ; y1 = (int) event.gety (); GetPosition (x1, y1);} break;//when there is already a touch point on the screen, and then one finger presses the screen, the case MotionEvent.ACTION_POINTER_DOWN:mode = Zoom;firsttouch = True;move = true; Startdis = Distance (event), if (Startdis > 10f) {//midpoint = Mid (event);} break;//finger away from the screen, when the screen has a finger on the screen, the corresponding case MotionEvent.ACTION_POINTER_UP:mode = 0;break;} if (mode = = ZOOM) {if (Scale > 2) {lastscale = 2;scale = 2;}  This.setscalex (scale), if (scale = = 1) {int L = 0;int T = 0;int r = this.getwidth (); int b = This.getheight (); This.layout (L, T, R, b);}} return true;} private void getPosition (int x12, int y12) {if (null = = Rects) {return;} for (int i = 1; I <= rects.size (); i++) {Rect r = rects.get (i-1), if (R.contains (X12, Y12)) {if (null! = Histogramoncl Icklistener) {Histogramonclicklistener.onclick (i);}}}} @SuppressLint ("Floatmath") public float distance (motionevent event) {Float dx = event.getx (1)-event.getx (0); float dy = Ev Ent.gety (1)-event.gety (0); float dz = floatmath.sqrt (dx * dx + dy * dy); return dz;} Private PointF Mid (Motionevent event) {Float dx = event.getx (1) + event.getx (0); float dy = event.gety (1) + event.gety (0); r Eturn New PointF (DX/2, DY/2);}







Android Developer's Custom view feature (i): Custom Column Chart

Related Article

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.