最近项目中用到了折线图效果,之前没做过这种图表的功能,从网上百度一些,发现跟我要的效果不一样,于是我就开始在别人写的代码基础上进行修改,修改是一件也很辛苦的事,因为首先你要看懂别人的代码,然后才能进行一定的修改和添加代码
下面就是我修改后的代码,夸自己一句,真的很不错
1 /** 2 * 备注: 3 * 作者:王莹 4 * 时间:2018/1/19. 5 * ~_~想睡觉了!! 6 * (~o~)~zZ我想睡啦~ 7 * π_π?打瞌睡 8 */ 9 10 public class DrawLineView extends View { 11 /** 12 * 上下文 13 */ 14 private Context mContext = null; 15 /** 16 * 画图区域的宽高 17 */ 18 private float width, height; 19 /** 20 * 纵坐标平均每一行的高度 21 */ 22 private float fRowHeight; 23 /** 24 * 横坐标平均每一列的宽带 25 */ 26 private float fColWidth = 0; 27 /**纵向显示个数*/ 28 // private static final int VERTICALCOUNT = 5; 29 /**横向显示个数*/ 30 // private static final int HORIZONTALCOUNT = 7; 31 /** 32 * 固定要显示的利率 33 */ 34 // private static final int CONSTANT_DISPLAY_RATE = 8; 35 /** 36 * 横纵向字体大小单位dp 37 */ 38 private static final int TEXTSIZE = 12; 39 /** 40 * 纵坐标、横坐标的字体画笔 41 */ 42 private Paint textPaint = null; 43 /** 44 * 横坐标画笔 45 */ 46 private Paint horizontalPaint = null; 47 /** 48 * 固定的虚线画笔 49 */ 50 private Paint dottedLinePaint = null; 51 /** 52 * 画Y轴的刻度线 53 */ 54 private Paint yLinePaint = null; 55 /** 56 * 画空心圆 57 */ 58 private Paint circlePaint = null; 59 /** 60 * 圆的半径 单位dp 61 */ 62 private int circleRadius = 3; 63 /** 64 * 折线画笔 65 */ 66 private Paint linePaint = null; 67 private Paint innerPaint = null; 68 /** 69 * 阴影画笔 70 */ 71 private Paint shadowPaint = null; 72 /** 73 * 阴影走过的路径 74 */ 75 private Path shadowPath = null; 76 77 private ListyList = new ArrayList (); 78 private List yListtext = new ArrayList (); 79 80 private List xList = new ArrayList (); 81 /** 82 * Y轴的五个刻度 83 */ 84 private List yRateList = new ArrayList (); 85 86 /** 87 * Y轴最大值 88 */ 89 private float maxY = 0; 90 /** 91 * 纵向设置的Y每一段的值 92 */ 93 private int verticalAnnualValueY = 0; 94 /** 95 * 横行字体宽带 96 */ 97 private float horizontalTextWidth = 0; 98 99 /**100 * 横向起始位置101 */102 private float xStart = 0;103 private float[] xPoint;104 private float[] yPoint;105 106 public DrawLineView(Context context) {107 super(context);108 initWillUsed(context);109 }110 111 public DrawLineView(Context context, AttributeSet attrs) {112 super(context, attrs);113 initWillUsed(context);114 }115 116 /**117 * 初始化将使用到的参数118 */119 private void initWillUsed(Context context) {120 mContext = context;121 122 textPaint = new Paint();123 textPaint.setColor(Color.parseColor("#B9C7DD"));124 textPaint.setAntiAlias(true);125 textPaint.setTextSize(ValueUtils.dip2px(mContext, TEXTSIZE));126 127 horizontalPaint = new Paint();128 horizontalPaint.setColor(Color.parseColor("#B9C7DD"));129 horizontalPaint.setAntiAlias(true);130 horizontalPaint.setStrokeWidth(1);131 132 yLinePaint = new Paint();133 yLinePaint.setColor(Color.parseColor("#B9C7DD"));134 yLinePaint.setAntiAlias(true);135 136 dottedLinePaint = new Paint();137 dottedLinePaint.setStyle(Paint.Style.STROKE);138 dottedLinePaint.setColor(Color.parseColor("#C5D1FF"));139 dottedLinePaint.setAntiAlias(true);140 141 circlePaint = new Paint();142 circlePaint.setColor(Color.parseColor("#6789FD"));143 circlePaint.setStyle(Paint.Style.STROKE);144 circlePaint.setAntiAlias(true);145 circlePaint.setStrokeWidth(1);146 147 linePaint = new Paint();148 linePaint.setColor(Color.parseColor("#6789FD"));149 linePaint.setStrokeWidth(2);150 linePaint.setAntiAlias(true);151 152 innerPaint = new Paint();153 innerPaint.setColor(Color.WHITE);154 innerPaint.setStyle(Paint.Style.FILL);155 innerPaint.setAntiAlias(true);156 157 158 }159 160 /**161 * 设置将要绘制的数据162 */163 public void setData(List xValuesList, List yValuesList, float currMaxY) {164 this.xList = xValuesList;165 this.yList = yValuesList;166 yListtext.clear();167 yRateList.clear();168 for (int i = 0; i < yList.size(); i++) {169 yListtext.add(yList.get(i));170 }171 xPoint = new float[xList.size()];172 yPoint = new float[xList.size()];173 174 if (currMaxY / yList.size() == currMaxY % yList.size()) {175 verticalAnnualValueY = (int) currMaxY / yList.size();176 } else {177 verticalAnnualValueY = (int) currMaxY / yList.size() + 1;178 }179 180 maxY = yList.size() * verticalAnnualValueY;181 182 183 for (int i = yListtext.size(); i >= 1; i--) {184 yRateList.add(verticalAnnualValueY * i);185 }186 setWillNotDraw(false);187 }188 189 @Override190 protected void onDraw(Canvas canvas) {191 super.onDraw(canvas);192 width = getWidth();193 height = getHeight();194 fRowHeight = (float) height / (yList.size()+1);195 xStart = 0;196 fColWidth = 0;197 shadowPaint = new Paint();198 shadowPaint.setAntiAlias(true);199 shadowPath = new Path();200 drawVertical(canvas);201 202 drawHorizontal(canvas);203 204 // drawDottedLine(canvas);205 206 drawYLine(canvas);207 208 drawLine(canvas);209 210 drawCircle(canvas);211 }212 213 /**214 * 画纵向数据215 */216 private void drawVertical(Canvas canvas) {217 Integer temp=0;218 for (int i = 0; i < yRateList.size()-1; i++) {219 for (int j = i + 1; j < yRateList.size(); j++) {220 if (yRateList.get(i)< yRateList.get(j)) { // 交换两数的位置221 temp = yRateList.get(i);222 yRateList.set(i,yRateList.get(j));223 // yRateList.get(i) = yRateList.get(j);224 yRateList.set(j,temp);225 // yRateList.get(j) = temp;226 }227 }228 }229 // //降序230 // Collections.reverse(yRateList);231 for (int i = 0; i < yRateList.size(); i++) {232 Integer verticalContent = yRateList.get(i);233 canvas.drawText(verticalContent + "", 0, i * fRowHeight + ValueUtils.dip2px(mContext, TEXTSIZE), textPaint);234 235 if (xStart < textPaint.measureText(verticalContent + "")) {236 xStart = textPaint.measureText(verticalContent + "");237 }238 }239 xStart = xStart * 3 / 2;240 }241 242 /**243 * 画横向数据244 */245 private void drawHorizontal(Canvas canvas) {246 for (int i = 0; i < xList.size(); i++) {247 String horizontalContent = xList.get(i);248 horizontalTextWidth = textPaint.measureText(horizontalContent);249 if (fColWidth == 0) {250 fColWidth = (width - xStart - horizontalTextWidth) / (xList.size() - 1);251 }252 canvas.drawText(horizontalContent, xStart + i * fColWidth - horizontalTextWidth / 2, yList.size() * fRowHeight + ValueUtils.dip2px(mContext, TEXTSIZE + 10), textPaint);253 254 // if (i == xList.size() - 1) {255 // canvas.drawLine(xStart, yList.size() * fRowHeight, fColWidth * i + horizontalTextWidth, yList.size() * fRowHeight, horizontalPaint);256 // }257 }258 }259 260 // /**261 // * 画固定8%的虚线262 // */263 // private void drawDottedLine(Canvas canvas) {264 // float dottedWidth = (maxY - CONSTANT_DISPLAY_RATE) * yList.size() * fRowHeight / maxY + ValueUtils.dip2px(mContext, TEXTSIZE);265 // Path path = new Path();266 // path.moveTo(xStart, dottedWidth);267 // path.lineTo(fColWidth * (xList.size() - 1) + horizontalTextWidth, dottedWidth);268 // PathEffect effects = new DashPathEffect(new float[]{4, 4, 4, 4}, 4f);269 // dottedLinePaint.setPathEffect(effects);270 // canvas.drawPath(path, dottedLinePaint);271 // }272 273 /**274 * 画Y轴的刻度线275 */276 private void drawYLine(Canvas canvas) {277 for (int i = 0; i < yList.size(); i++) {278 canvas.drawLine(xStart, i * fRowHeight + ValueUtils.dip2px(mContext, TEXTSIZE), fColWidth * (xList.size()), i * fRowHeight + ValueUtils.dip2px(mContext, TEXTSIZE), yLinePaint);279 }280 }281 282 /**283 * 画空心圆284 */285 private void drawCircle(Canvas canvas) {286 for (int i = 0; i < xList.size(); i++) {287 canvas.drawCircle(xPoint[i], yPoint[i], ValueUtils.dip2px(mContext, circleRadius), circlePaint);288 289 float innerValue = ValueUtils.dip2px(mContext, circleRadius) - 1.6F;290 291 innerPaint.setColor(Color.WHITE);292 innerPaint.setStyle(Paint.Style.FILL);293 innerPaint.setAntiAlias(true);294 canvas.drawCircle(xPoint[i], yPoint[i], innerValue, innerPaint);295 }296 }297 298 /**299 * 画折线 和 阴影300 */301 private void drawLine(Canvas canvas) {302 int maxHeightPoint = 0;//记录最高的点303 float maxHeight = 0;304 for (int i = 0; i < xList.size(); i++) {305 xPoint[i] = xStart + i * fColWidth;306 307 if (maxHeight < yList.get(i)) {308 maxHeight = yList.get(i);309 maxHeightPoint = i;310 }311 yPoint[i] = (maxY - yList.get(i)) / maxY * yList.size() * fRowHeight + ValueUtils.dip2px(mContext, TEXTSIZE);312 313 if (i > 0) {314 canvas.drawLine(xPoint[i - 1], yPoint[i - 1], xPoint[i], yPoint[i], linePaint);315 if (i == 1) {316 shadowPath.moveTo(xPoint[i - 1], yPoint[i - 1]);317 }318 shadowPath.lineTo(xPoint[i], yPoint[i]);319 }320 }321 shadowPath.lineTo(xPoint[xList.size() - 1], yList.size() * fRowHeight);322 shadowPath.lineTo(xPoint[0], yList.size() * fRowHeight);323 shadowPath.close();324 Shader lShader = new LinearGradient(0, yPoint[maxHeightPoint], 0, yList.size() * fRowHeight, Color.parseColor("#BFC5D1FF"), Color.parseColor("#BFFDFDFF"), Shader.TileMode.REPEAT);325 shadowPaint.setShader(lShader);326 canvas.drawPath(shadowPath, shadowPaint);327 }328 }
用来也很简单呀!
private void initLineDatas() {// cv_chartView.setShowNum(listarray.size()); maxlist = new ArrayList<>(); for (int i = 0; i < listarray.size(); i++) { maxlist.add(listarray.getJSONObject(i).getFloatValue("sq")); ydatas.add(listarray.getJSONObject(i).getInteger("sq")); } float maxValueY = Collections.max(maxlist); cv_chartView.setData(xdata, ydatas, maxValueY); cv_chartView.postInvalidate(); }
不过注意的是,如果你需要切换数据或者改其他数据,肯定都要吧之前数据清掉的哦!希望可以帮到其他小伙伴啦!
把效果图也发给大家吧!
跟效果图不一样的是我加了圆点