package com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.render; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.RectF; import android.graphics.Shader; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.animate.LAnimator; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.charts.LineChart; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.data.Entry; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.data.Line; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.data.Lines; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.manager.MappingManager; import com.mm.android.deviceaddmodule.mobilecommon.widget.linechart.utils.SingleF_XY; import java.util.List; public class LineRender extends BaseRender { LineChart lineChart; Lines _lines; Paint _PaintLine; Paint _PaintCircle; Paint _PaintLegend; Path _PathLine; LAnimator _LAnimator; Bitmap _drawBitmap; Canvas softwareCanvas = new Canvas(); public LineRender(RectF rectMain, MappingManager _MappingManager, Lines _lines, LineChart lineChart) { super(rectMain, _MappingManager); this._lines = _lines; this.lineChart = lineChart; this._LAnimator = lineChart.get_LAnimator(); _PaintLine = new Paint(Paint.ANTI_ALIAS_FLAG); _PaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG); _PaintLegend = new Paint(Paint.ANTI_ALIAS_FLAG); _PathLine = new Path(); } public void onChartSizeChanged(int w, int h) { if (w > 0 && h > 0) { _drawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); softwareCanvas.setBitmap(_drawBitmap); } } public void render(Canvas canvasSrc) { if (_lines == null) { return; } Canvas canvas = null; // layout editor 状态下 _drawBitmap 是没有的 if (null != _drawBitmap) { canvas = softwareCanvas; canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); } else { canvas = canvasSrc; } canvas.save(); // canvas.clipRect(_rectMain); // 限制绘制区域 RectF rectF = new RectF(_rectMain); rectF.top = _rectMain.top - 20; rectF.bottom = _rectMain.bottom + 20; canvas.clipRect(rectF); // 限制绘制区域 // 绘制折线 和 折线上的圆点 for (Line line : _lines.getLines()) { if (!line.isEnable()) { continue; } drawLine_Circle(canvas, line); } canvas.restore(); // 绘制每条线的 legend // for (int i = 0; i < _lines.getLines().size(); i++) { // Line line = _lines.getLines().get(i); // if (!line.isEnable()) { // continue; // } // drawLegend(canvas, line, i); // } if (_drawBitmap != null) { canvasSrc.drawBitmap(_drawBitmap, 0, 0, null); } } private void drawLine_Circle(Canvas canvas, Line line) { // HighLight highLight = new HighLight(); // highLight.setHighLightColor(line.getLineColor()); _PaintLine.setStrokeWidth(line.getLineWidth()); _PaintLine.setColor(line.getLineColor()); _PaintLine.setStyle(Paint.Style.STROKE); _PaintCircle.setStrokeWidth(line.getLineWidth()); _PaintCircle.setColor(line.getLineColor()); List list = line.getEntries(); // check if (list == null || list.size() == 0) { return; } // 考虑只有一个点的情况 if (list.size() == 1) { Entry hit = list.get(0); SingleF_XY xy = _MappingManager.getPxByEntry(hit); canvas.drawCircle(xy.getX(), xy.getY(), line.getCircleR(), _PaintCircle); return; } double xMin_Visiable = lineChart.getVisiableMinX(); double xMax_Visiable = xMin_Visiable + (lineChart.getVisiableMaxX() - xMin_Visiable) * _LAnimator.get_hitValueX();// 考虑动画 int minIndex = Line.getEntryIndex(list, xMin_Visiable, Line.Rounding.DOWN); int maxIndex = Line.getEntryIndex(list, xMax_Visiable, Line.Rounding.UP); if (Math.abs(maxIndex - minIndex) == 0) { return; } if ((maxIndex - minIndex) > 1500) { _PaintLine.setAntiAlias(false);// 考虑性能 } else { _PaintLine.setAntiAlias(true); } _PathLine.reset(); int breakI = -1; for (int i = minIndex; i <= maxIndex; i++) { Entry entry = list.get(i); // 考虑这个点是否断掉 if (entry.isNull_Y()) { breakI = i; continue; } float sx = _MappingManager.v2p_x(entry.getX()); float sy = getAnimateY(_MappingManager.v2p_y(entry.getY())); if (i == minIndex || i == breakI + 1) { _PathLine.moveTo(sx, sy); } else { _PathLine.lineTo(sx, sy); } if (line.isDrawCircle()) { SingleF_XY xy = _MappingManager.getPxByEntry(entry); canvas.drawCircle(xy.getX(), getAnimateY(xy.getY()), line.getCircleR(), _PaintCircle); // 把最后点一个绘制出来 if (i == maxIndex - 1) { Entry last = list.get(maxIndex); xy = _MappingManager.getPxByEntry(last); ///////////////////////////////////////////// 考虑动画效果 ////////////////////////////////////////// canvas.drawCircle(xy.getX(), getAnimateY(xy.getY()), line.getCircleR(), _PaintCircle); } } } canvas.drawPath(_PathLine, _PaintLine); // 有断掉的点,就不考虑填充了 if (breakI != -1) { return; } // 考虑填充 if (line.isFilled()) { Entry start = list.get(minIndex); Entry end = list.get(maxIndex); float sx = _MappingManager.v2p_x(start.getX()); float sy = getAnimateY(_MappingManager.v2p_y(start.getY())); float ex = _MappingManager.v2p_x(end.getX()); float ey = getAnimateY(_MappingManager.v2p_y(end.getY())); float maxY = Math.max(sy, ey); _PathLine.lineTo(ex, lineChart.get_MainPlotRect().bottom); _PathLine.lineTo(sx, lineChart.get_MainPlotRect().bottom); _PathLine.close(); _PaintLine.setStyle(Paint.Style.FILL); _PaintLine.setAlpha(50); Shader shader = new LinearGradient(0, maxY, 0, 0, line.getLineColor(), line.getLineColor() / 50, Shader.TileMode.CLAMP); _PaintLine.setShader(shader); canvas.drawPath(_PathLine, _PaintLine); _PaintLine.setStyle(Paint.Style.STROKE); _PaintLine.setShader(null); } } RectF _RectFBuffer = new RectF(); public void onDataChanged(Lines lines) { _lines = lines; } private float getAnimateY(float src) { return lineChart.get_MainPlotRect().bottom - (lineChart.get_MainPlotRect().bottom - src) * _LAnimator.get_hitValueY(); } }