最近项目中用到了折线图效果,之前没做过这种图表的功能,从网上百度一些,发现跟我要的效果不一样,于是我就开始在别人写的代码基础上进行修改,修改是一件也很辛苦的事,因为首先你要看懂别人的代码,然后才能进行一定的修改和添加代码
下面就是我修改后的代码,夸自己一句,真的很不错
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 List<Integer> yList = new ArrayList<Integer>(); 78 private List<Integer> yListtext = new ArrayList<Integer>(); 79 80 private List<String> xList = new ArrayList<String>(); 81 /** 82 * Y轴的五个刻度 83 */ 84 private List<Integer> yRateList = new ArrayList<Integer>(); 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<String> xValuesList, List<Integer> 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 @Override 190 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 }
用来也很简单呀!
<com.egojit.android.sops.views.Chart.DrawLineView android:id="@+id/cv_chartView" android:layout_width="match_parent" android:layout_height="300dp" android:visibility="gone" > </com.egojit.android.sops.views.Chart.DrawLineView>
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(); }
不过注意的是,如果你需要切换数据或者改其他数据,肯定都要吧之前数据清掉的哦!希望可以帮到其他小伙伴啦!
把效果图也发给大家吧!
跟效果图不一样的是我加了圆点