<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本篇介紹線性圖示RecyclerLineChart 的繪製,對於圖表的公共部分X、Y軸,背景Board等的繪製先前章節已經有過介紹,這裡不再重複;以及高亮選中頂部的poupWindow基本的繪製邏輯跟BarChart類似,可參照之前章節。所以針對LineChart,這裡只介紹主體圖表的繪製邏輯,以及線性表底部的drawFillColor填充。
首先介紹主體圖表的邏輯,與BarChart不同之處在於,BartChart的每個Item的繪製比較獨立,而LineChart對於當前的Item,需要找到PreItem或者NextItem中的Y的點進行drawLine, 相比而言稍顯複雜一些。圖表的中間位置的Line還比較容易繪製,圖表左右邊界是LineChart繪製最難的地方。
整個的繪製邏輯第一章節有介紹在Render類中,這裡的話是LineChartRender的drawLineChartWithoutPoint 方法裡,這個方法程式碼比較長,分段介紹:
private <T extends BarEntry> void drawLineChartWithoutPoint(Canvas canvas, RecyclerView parent, YAxis mYAxis) { final float parentRightBoard = parent.getWidth() - parent.getPaddingRight(); final float parentLeft = parent.getPaddingLeft(); BaseBarChartAdapter adapter = (BaseBarChartAdapter) parent.getAdapter(); List<T> entryList = adapter.getEntries(); final int childCount = parent.getChildCount(); int adapterPosition; for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); T barEntry = (T) child.getTag(); if (barEntry.getY() == 0) { continue; } adapterPosition = parent.getChildAdapterPosition(child); RectF rectF = ChartComputeUtil.getBarChartRectF(child, parent, mYAxis, mLineChartAttrs, barEntry); PointF pointF2 = new PointF((rectF.left + rectF.right) / 2, rectF.top); // 這裡還有好多繪製邏輯程式碼 }//end for }// end drawLineChartWithoutPoint
整個繪製繪製依次遍歷 Adapter中當前展現的點,總共childcount 個,遍歷的當前點位pointF2, 以pointF2 為基準接下來會涉及找 pointF0,pointF1, 這兩在pointF2左邊(假設存在的情況下);pointF3, pointF4, 這兩個點在PointFd2的右邊,之所以要找左右各兩個點是處理邊界情況。
連線pointF1、pointF2。
if (i < childCount - 1) {//這裡的LayoutManager設定的reverse倒敘,所以i+1在i的左邊i對應的是pointF2 View pointF1Child = parent.getChildAt(i + 1); T barEntryLeft = (T) pointF1Child.getTag(); //這裡的RectF跟之前的Barchart類似,為ItemView中除去space後所佔的RectF區域,其中pointF1的X為RectF的X軸方向的中心。 RectF rectFLeft = ChartComputeUtil.getBarChartRectF(pointF1Child, parent, mYAxis, mLineChartAttrs, barEntryLeft); //找到PointF1 PointF pointF1 = new PointF((rectFLeft.left + rectFLeft.right) / 2, rectFLeft.top); //parentLeft為左邊界, parentRightBoard 為Chart的右邊界 if (pointF1.x >= parentLeft && pointF2.x <= parentRightBoard) { float[] pointsOut = new float[]{pointF1.x, pointF1.y, pointF2.x, pointF2.y}; drawChartLine(canvas, pointsOut);//繪製正常情況下的Line。 drawFill(parent, mLineChartAttrs, canvas, pointF1, pointF2, rectF.bottom); //其它邊界繪製邏輯。 }//end if
以上的情況是pointF1.x 在Chart內,見圖, 黃色為當前的PointF1, 紫色為PointF2, 上面程式碼李drawLine繪製的是PointF1跟PointF2之前的連線。
繼續看上面的那個圖,要繪製PointF1到Chart左邊邊界的線段,需要繼續找到PointF0,然後用PointF0、PointF1與Chart相交得到上圖黑色圈裡的點,記為pointFIntercept, drawLine(pointFIntercept, PointF1)
if (pointF1Child.getLeft() < parentLeft) {//左邊界,處理pointF1值顯示出來了的情況。 if (adapterPosition + 2 < entryList.size()) { float x = pointF1.x - pointF1Child.getWidth(); T barEntry0 = entryList.get(adapterPosition + 2); float y = ChartComputeUtil.getYPosition(barEntry0, parent, mYAxis, mLineChartAttrs); PointF pointF0 = new PointF(x, y); //PointF0、PointF1 跟Chart的交點pointFIntercept PointF pointFIntercept = ChartComputeUtil.getInterceptPointF(pointF0, pointF1, parentLeft); float[] points = new float[]{pointFIntercept.x, pointFIntercept.y, pointF1.x, pointF1.y}; drawChartLine(canvas, points); drawFill(parent, mLineChartAttrs, canvas, pointFIntercept, pointF1, rectF.bottom); } }
上面是 pointF1.x >= parentLeft,在左邊界內的情況,當pointF1.x < parentLeft時,rectLeft 出來一小部分的情況,如下圖所示:紫色為當前的PointF2點
這時需要求PointF1、PointF2跟Chart相交的點pointF, 然後drawLine(pointF, PointF2)即可, 見程式碼:
if (pointF1.x < parentLeft && pointF1Child.getRight() >= parentLeft) {//左邊界,處理pointF1值沒有顯示出來 PointF pointF = ChartComputeUtil.getInterceptPointF(pointF1, pointF2, parentLeft); float[] points = new float[]{pointF.x, pointF.y, pointF2.x, pointF2.y}; drawChartLine(canvas, points); drawFill(parent, mLineChartAttrs, canvas, pointF, pointF2, rectF.bottom); }
處理完左邊界的繪製,右邊界的繪製跟左邊界大致一樣,PointF2 往右兩個點PointF3, PointF4; 注意這裡RecyclerView的LayoutManager為reverse, 所以當 PointF2對應的下標為i時, PointF3對應的為i-1, PointF4為i-2.
然後就是分情況討論PointF3.x 是否在Chart範圍內,跟parentRightBorad比較即可。
看PointF3.x 在 Chart範圍內的情況,如圖:紫色為PointF2點,黃色為PonitF3點,黑色為PointF3,PointF4跟Chart的交點,這裡只需要繪製PointF3跟交點之間的Line;PointF2、PointF3之間的Line 在當黃色點遍歷到i時,紫色點位PointF1,所以這裡不需要重複繪製了。
if (pointF3.x < parentRightBoard) {//pointF3 在界內。 if (adapterPosition - 2 > 0) { float xInner = pointF3.x + child.getWidth(); T barEntry4 = entryList.get(adapterPosition - 2); float yInner = ChartComputeUtil.getYPosition(barEntry4, parent, mYAxis, mLineChartAttrs); PointF pointF4 = new PointF(xInner, yInner);//找到PointF4. PointF pointFInterceptInner = ChartComputeUtil.getInterceptPointF(pointF3, pointF4, parentRightBoard); float[] pointsInner = new float[]{pointF3.x, pointF3.y, pointFInterceptInner.x, pointFInterceptInner.y}; drawChartLine(canvas, pointsInner); drawFill(parent, mLineChartAttrs, canvas, pointF3, pointFInterceptInner, rectF.bottom); } }
最後就是 pointF3.x >parentRightBoard的情況,見圖:紫色為PointF2, 黃色為 PointF2、PointF3跟Chart的交點:
程式碼邏輯如下:
if (pointF3.x > parentRightBoard) {//在Chart之外。 PointF pointFIntercept = ChartComputeUtil.getInterceptPointF(pointF2, pointF3, parentRightBoard); float[] points = new float[]{pointF2.x, pointF2.y, pointFIntercept.x, pointFIntercept.y}; drawChartLine(canvas, points); drawFill(parent, mLineChartAttrs, canvas, pointFIntercept, pointF2, rectF.bottom); }
以上的邊界處理中涉及到的工具類方法求相交點,簡單的數學公司帶入:
public static PointF getInterceptPointF(PointF pointF1, PointF pointF2, float x) { float width = Math.abs(pointF1.x - pointF2.x); float height = Math.abs(pointF1.y - pointF2.y); float interceptWidth = Math.abs(pointF1.x - x); float interceptHeight = interceptWidth * 1.0f / width * height; float y; if (pointF2.y < pointF1.y) { y = pointF1.y - interceptHeight; } else { y = pointF1.y + interceptHeight; } return new PointF(x, y); }
見以上圖表中的紅色半透明的FillColor的繪製,每次drawLine()緊跟著就是drawFill(), 以下是drawFill的邏輯,跟X軸構建一個path,然後drawPath 即可:
private void drawFill(RecyclerView parent, LineChartAttrs mBarChartAttrs, Canvas canvas, PointF pointF, PointF pointF1, float bottom) { if (mBarChartAttrs.enableLineFill) { float yBottom = parent.getBottom() - parent.getPaddingBottom(); float yTop = parent.getTop() + parent.getPaddingTop(); LinearGradient mLinearGradient = new LinearGradient( 0, yBottom, 0, yTop, new int[]{ mBarChartAttrs.lineShaderBeginColor, mBarChartAttrs.lineShaderEndColor}, null, Shader.TileMode.CLAMP ); mLineFillPaint.setShader(mLinearGradient); Path path = ChartComputeUtil.createColorRectPath(pointF, pointF1, bottom); LineChartDrawable drawable = new LineChartDrawable(mLineFillPaint, path); drawable.draw(canvas); } }
設定了一個Color的Linear漸變從bottom到top.
至此,RecyclerLineChart的主體圖表繪製邏輯介紹完畢。還有部分的細節,當前Point帶圓圈,以及邊界圓圈的繪製等,選中圓圈的處理等多處細節,讀者想了解的,可以GitHub上下載看原始碼demo, 連線在本專欄的第一篇裡有連結。
以上就是Android RecyclerLineChart實現圖表繪製教學的詳細內容,更多關於Android RecyclerLineChart圖表繪製的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45