自定义折线图加上背景阴影效果

最近项目中用到了折线图效果,之前没做过这种图表的功能,从网上百度一些,发现跟我要的效果不一样,于是我就开始在别人写的代码基础上进行修改,修改是一件也很辛苦的事,因为首先你要看懂别人的代码,然后才能进行一定的修改和添加代码

下面就是我修改后的代码,夸自己一句,真的很不错

  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();
    }

不过注意的是,如果你需要切换数据或者改其他数据,肯定都要吧之前数据清掉的哦!希望可以帮到其他小伙伴啦!

把效果图也发给大家吧!

跟效果图不一样的是我加了圆点

posted on 2018-02-01 10:52  oooo呼呼  阅读(996)  评论(0编辑  收藏  举报