Previously wrote a chart lib, but the speed of development, most difficult to keep up with the pace of product demand changes, so modified the original chart library, support chart can be integrated table display corresponding class, with the curve to replace the polyline, support multi-curve display, increase the display of animation, Added customizable properties to support horizontal histogram and stacked histogram, as well as multi-graph and pie chart display
1.
2. How to use the various charts 1. Pie chart This is the same as the original use, but added an animation, you can see the previous article, pie chart use. 2. Horizontal multi-bar chart 2.1 XML layout
<wellijohn.org.varchart.hor_bar_with_line_chart.ChartLine android:id="@+id/chartline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/white" app:default_x_visible_num="4.2"//一个屏幕中显示多少列 app:y_interval="40dp"//Y轴的间距 app:y_num_text_max_width="56dp"//y轴左边的文字的宽度 />还有y_visible_num:y轴需要显示几列
2.2 Data settings
public class Horbaractivity extends Appcompatactivity {//display coordinate points private chartline mchartline; The coordinate point of multi-line is private list<list<dotvo>> mmullistdisdots; X-axis point private string[] mxdots = new string[]{"08/18", "08/19", "08/20", "08/21", "08/22", "08/2 3 "," 08/24 "," 08/25 "," 08/26 "," 08/27 "," 08/28 "," 08/29 "," 09/01 "," 09/02 "," 09/23 ",}; Private double Mmax = 44; Private random Rand = new Random (); Private list<categoryvo> mcategorylist; @Override protected void OnCreate (@Nullable Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_hor_bar); Initview (); Initmultestdata (); Initcategorylist (); try {mchartline.setyaxismaxvalue (Mmax). Setxdots (Mxdots). Setanimationopen (True). Setlistdisdots (MMulListDisDots) . Setcategorylist (mcategorylist). ReDraw (); } catch (Ycoordinateexception e) { LOG.D ("Mainactivity", "OnCreate:"); E.printstacktrace (); }}/** * Histogram data, is a list, a Categoryvo, is a column to add a bar * categoryvo:{* Card Coupon Class Purpose name * Private Strin G CategoryName; * The value of each card coupon class * Private list<string> categoryvaluelist; *} */private void Initcategorylist () {mcategorylist = new arraylist<> (); Mcategorylist.add (New Categoryvo ()); Mcategorylist.add (New Categoryvo ()); Mcategorylist.add (New Categoryvo ()); }/** * Initialization curve, private list<list<dotvo>> mmullistdisdots; * List<dotvo>> is a graph, */private void Initmultestdata () {mmullistdisdots = new arraylist<> ( ); for (int i = 0; i < 3; i++) {arraylist<dotvo> temp = new ArrayList (); Dotvo tempdotvo = new Dotvo ("08/18", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO); Dotvo tempDotVo1 = new Dotvo ("08/19", Rand.nextinT ((int) mmax)); Temp.add (TEMPDOTVO1); Dotvo TempDotVo2 = new Dotvo ("08/20", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO2); Dotvo TempDotVo3 = new Dotvo ("08/21", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO3); Dotvo TempDotVo4 = new Dotvo ("08/22", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO4); Dotvo tempDotVo5 = new Dotvo ("08/23", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO5); Dotvo TempDotVo6 = new Dotvo ("09/02", Rand.nextint ((int) mmax)); Temp.add (TEMPDOTVO6); Mmullistdisdots.add (temp); }} private void Initview () {mchartline = Findviewbyid (r.id.chartline); }}
3. Overlay Histogram 3.1 XML layout
<wellijohn.org.varchart.overlay_bar_with_line_chart.OverLayBarChartLine android:id="@+id/overlay_chart_line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/white" android:visibility="visible" app:overlay_default_x_visible_num="4.2" app:overlay_y_interval="40dp" app:overlay_y_num_text_max_width="56dp" />
3.2 Data settings, like 2.2 3. The implementation of several key points 3.1 width needs to be overridden, because the width of the control is greater than the width of the screen, and the width is composed of the distance between the point and spacing of the displayed x-axis, and the width of the text of the y-coordinate of the onmeasure.
int widthparentmeasuremode = Measurespec.getmode (Widthmeasurespec); int widthparentmeasuresize = measurespec.getsize (Widthmeasurespec); int heightparentmeasuremode = Measurespec.getmode (Heightmeasurespec); int heightparentmeasuresize = measurespec.getsize (Heightmeasurespec); int resultwidthsize = 0; int resultheightsize = 0; int resultwidthmode = measurespec.exactly;//is used to calculate the Childview int resultheightmode = measurespec.exactly; int paddingwidth = Getpaddingleft () + getpaddingright (); int paddingheight = getpaddingtop () + Getpaddingbottom (); Viewgroup.layoutparams THISLP = Getlayoutparams (); Switch (Widthparentmeasuremode) {//parent class is not restricted to subclass case measurespec.unspecified://This represents in the layout Wrote dead width if (thislp.width > 0) {resultwidthsize = Thislp.width; Resultwidthmode = measurespec.exactly; } else { resultwidthsize = (int) (Getymaxtextwidth () + mxinterval * mxdots.length); Resultwidthmode = measurespec.unspecified; } break; Case Measurespec.at_most://This representative wrote dead width if in the layout (Thislp.width > 0) {resul Twidthsize = Thislp.width; Resultwidthmode = measurespec.exactly; } else if (thislp.width = = ViewGroup.LayoutParams.MATCH_PARENT) {resultwidthsize = Math.max (0, WIDTHPA Rentmeasuresize-paddingwidth); Resultwidthmode = Measurespec.at_most; } else if (thislp.width = = ViewGroup.LayoutParams.WRAP_CONTENT) {resultwidthsize = (int) (GETYMAXTEXTW Idth () + mxinterval * mxdots.length); Resultwidthmode = Measurespec.at_most; } break; Case measurespec.exactly://This representative writes dead width if in the layout (Thislp.width &Gt 0) {resultwidthsize = Math.min (widthparentmeasuresize, thislp.width); Resultwidthmode = measurespec.exactly; } else if (thislp.width = = ViewGroup.LayoutParams.MATCH_PARENT) {resultwidthsize = Widthparentmeasures Ize Resultwidthmode = measurespec.exactly; } else if (thislp.width = = ViewGroup.LayoutParams.WRAP_CONTENT) {resultwidthsize = (int) (GETYMAXTEXTW Idth () + mxinterval * mxdots.length); Resultwidthmode = Measurespec.at_most; } break; } setmeasureddimension (Measurespec.makemeasurespec (Resultwidthsize, Resultwidthmode), MeasureSpec.ma Kemeasurespec (Resultheightsize, Resultheightmode));
3.2 Planning fixed area, in the part of the outside of the area is not visible, this in the previous use of the bitmap to achieve, always feel awkward, back to read the official source of the time, understand the canvas of the Cliprect method, we draw this piece, OnDraw method call
int clipRestoreCount = canvas.save(); canvas.clipRect(mContentRect);//绘制之前调用 doDraw();//进行想要的绘制 canvas.restoreToCount(clipRestoreCount);//绘制完成调用restoreToCount恢复到绘制这块之前的状态
3.3 Animation We can basically use valueanimator to achieve, such as pie chart: his one draw is 0-360 angle of change, we can
private void startPathAnim(long duration) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 360); valueAnimator.setDuration(duration); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mDrawAngle = (float) animation.getAnimatedValue(); ViewCompat.postInvalidateOnAnimation(CirclePercentChart.this); } }); valueAnimator.start(); }
Then through the mdrawangle to control the angle of each draw, so that you can have a sense of drawing from 0-360 degrees, the histogram of the animation is the same, status quo.
Algorithm of 3.4 Bezier curve drawing
if (i == 0) {// 第一条为二阶贝塞尔 path.moveTo(mDots[0], mDots[1] + (mLastHorLineY - mDots[1]) * mPhaseY);// 起点 } else { float cpx = preX + (mDots[0] - preX) / 2.0f; path.cubicTo(cpx, preY + (mLastHorLineY - preY) * mPhaseY, cpx, mDots[1] + (mLastHorLineY - mDots[1]) * mPhaseY, mDots[0], mDots[1] + (mLastHorLineY - mDots[1]) * mPhaseY);}
In drawing the Bezier curve, I carefully checked the calculation rules of these control points, there are based on three points, to calculate two control points, but so drawn out in three points inside the curve is very smooth, but in the next fourth point of convergence, feeling is not very good, so I still use the above calculation method to calculate the control point, The algorithm I post, the parameters are the x and Y coordinates and the bending factor
public static controlponits getcontrolpoints (double x0, double y0, double x1, double y1, double x2, double y2, double para mcoefficient) {Double d01 = math.sqrt (Math.pow (x1-x0, 2) + Math.pow (y1-y0, 2)); Double D12 = math.sqrt (Math.pow (x2-x1, 2) + Math.pow (y2-y1, 2)); Double FA = paramcoefficient * D01/(d01 + D12); Scaling factor for triangle Ta Double fb = paramcoefficient * D12/(d01 + D12); Ditto for Tb, simplifies to fb=t-fa double p1x = X1-fa * (x2-x0); X2-x0 is the width of triangle T double p1y = Y1-fa * (y2-y0); Y2-y0 is the height of T double p2x = x1 + fb * (x2-x0); Double p2y = y1 + fb * (Y2-Y0); Controlponits tempcontrolpoints = new Controlponits (); Tempcontrolpoints.beforecontrolpointx = (float) p1x; Tempcontrolpoints.beforecontrolpointy = (float) p1y; Tempcontrolpoints.aftercontrolpointx = (float) p2x; Tempcontrolpoints.aftercontrolpointy= (float) p2y; return tempcontrolpoints; }
3.library Introduction Method
step 1. Add it in your root build.gradle at the end of repositories:allprojects {repositories {...maven { url ‘https://jitpack.io‘ }}}Step 2. Add the dependencydependencies { compile ‘com.github.WelliJohn:charts:1.0.0‘}
GitHub address, your point like and star is the biggest driver of my continued open source.
Android a library of icons containing tables