Android绘制动态折线图
程序员文章站
2022-04-12 11:45:29
所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果。基于这个效果,这里使用surfaceview进行制图。
实现步奏如下:
(1): 这里新...
所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果。基于这个效果,这里使用surfaceview进行制图。
实现步奏如下:
(1): 这里新建一个绘图chartview,继承surfaceview并实现surfaceholder.callback , runnable接口,主要绘图工作在子线程中完成。
(2):现实 surfaceholder.callback接口的三个方法,并在 surfacecreated中开启子线程进行绘图。
(3):重写ontouchevent方法,在move事件中,根据手指的滑动距离计算偏移量,具体实现请看代码。
(4): 这里的折线图的坐标值是随意添加的,可以在实际项目中根据需求自己添加。
(5):此例中有大量从集合中添加和删除元素,建议使用linkedlist来进行保存数据。
自定义chartview:
public class chartview extends surfaceview implements surfaceholder.callback , runnable { private context mcontext; private paint mpaint; private resources res; private displaymetrics dm; private int canvasheight; private int canvaswidth; private int bheight = 0; private int bwidth; private boolean ismeasure = true; private boolean canscrollright = true; private boolean canscrollleft = true; //y轴最大值 private int maxvalue; //y轴间隔值 private int averagevalue; private int margintop = 20; private int marginbottom = 80; //曲线上的总点数 private point[] mpoints; //纵坐标值 private linkedlist<double> yrawdata; //横坐标值 private linkedlist<string> xrawdata; //根据间隔计算出的每个x的值 private linkedlist<integer> xlist = new linkedlist<>(); private linkedlist<string> xpredata = new linkedlist<>(); private linkedlist<double> ypredata = new linkedlist<>(); private linkedlist<string> xlastdata = new linkedlist<>(); private linkedlist<double> ylastdata = new linkedlist<>(); private int spacingheight; private surfaceholder holder; private boolean isrunning = true; private int lastx; private int offset; private rect mrect; private int xaveragevalue = 0; public chartview(context context) { this(context , null); } public chartview(context context , attributeset attrs) { super(context, attrs); this.mcontext = context; initview(); } private void initview() { this.res = mcontext.getresources(); this.mpaint = new paint(paint.anti_alias_flag); dm = new displaymetrics(); windowmanager wm = (windowmanager) mcontext.getsystemservice(context.window_service); wm.getdefaultdisplay().getmetrics(dm); xpredata.add("05-18"); xpredata.add("05-17"); xpredata.add("05-16"); xpredata.add("05-15"); xpredata.add("05-14"); xpredata.add("05-13"); ypredata.add(4.53); ypredata.add(3.45); ypredata.add(6.78); ypredata.add(5.21); ypredata.add(2.34); ypredata.add(6.32); xlastdata.add("05-26"); xlastdata.add("05-27"); xlastdata.add("05-28"); xlastdata.add("05-29"); xlastdata.add("05-30"); xlastdata.add("05-31"); ylastdata.add(2.35); ylastdata.add(5.43); ylastdata.add(6.23); ylastdata.add(7.33); ylastdata.add(3.45); ylastdata.add(2.45); holder = this.getholder(); holder.addcallback(this); } @override protected void onsizechanged(int w , int h , int oldw , int oldh) { if (ismeasure) { this.canvasheight = getheight(); this.canvaswidth = getwidth(); if (bheight == 0) { bheight = canvasheight - marginbottom; } bwidth = dip2px(30); xaveragevalue = (canvaswidth - bwidth) / 7; ismeasure = false; } } @override public void run() { while (isrunning) { drawview(); try { thread.sleep(100); } catch (interruptedexception e) { e.printstacktrace(); } } } private void drawview() { canvas canvas = holder.lockcanvas(); canvas.drawcolor(color.white); mpaint.setcolor(res.getcolor(r.color.color_f2f2f2)); drawallxline(canvas); mrect = new rect(bwidth - 3, margintop - 5 , bwidth + (canvaswidth - bwidth) / yrawdata.size() * (yrawdata.size() - 1) + 3, bheight + margintop + marginbottom); //锁定画图区域 canvas.cliprect(mrect); drawallyline(canvas); mpoints = getpoints(); mpaint.setcolor(res.getcolor(r.color.color_ff4631)); mpaint.setstrokewidth(dip2px(2.5f)); mpaint.setstyle(paint.style.stroke); drawline(canvas); mpaint.setstyle(paint.style.fill); for (int i = 0 ; i < mpoints.length ; i++) { canvas.drawcircle(mpoints[i].x , mpoints[i].y , 5 , mpaint); } holder.unlockcanvasandpost(canvas); } //绘制折线图 private void drawline(canvas canvas) { point startp = null; point endp = null; for (int i = 0 ; i < mpoints.length - 1; i++) { startp = mpoints[i]; endp = mpoints[i + 1]; canvas.drawline(startp.x , startp.y , endp.x , endp.y , mpaint); } } //绘制所有的纵向分割线 private void drawallyline(canvas canvas) { for (int i = 0 ; i < yrawdata.size() ; i++) { if (i == 0) { canvas.drawline(bwidth, margintop , bwidth, bheight + margintop , mpaint); } if (i == yrawdata.size() - 1) { canvas.drawline(bwidth + xaveragevalue * i, margintop , bwidth + xaveragevalue * i , bheight + margintop , mpaint); } xlist.add(bwidth + xaveragevalue * i); canvas.drawline(bwidth + xaveragevalue * i + offset, margintop , bwidth + xaveragevalue * i + offset , bheight + margintop , mpaint); drawtext(xrawdata.get(i) , bwidth + xaveragevalue * i - 30 + offset, bheight + dip2px(26) , canvas); } } //绘制所有的横向分割线 private void drawallxline(canvas canvas) { for (int i = 0 ; i < spacingheight + 1 ; i++) { canvas.drawline(bwidth , bheight - (bheight / spacingheight) * i + margintop , bwidth + xaveragevalue * (yrawdata.size() - 1) , bheight - (bheight / spacingheight) * i + margintop , mpaint); drawtext(string.valueof(averagevalue * i) , bwidth / 2 , bheight - (bheight / spacingheight) * i + margintop, canvas); } } //绘制坐标值 private void drawtext(string text , int x , int y , canvas canvas) { paint p = new paint(paint.anti_alias_flag); p.settextsize(dip2px(12)); p.setcolor(res.getcolor(r.color.color_999999)); p.settextalign(paint.align.left); canvas.drawtext(text , x , y , p); } @override public void surfacecreated(surfaceholder surfaceholder) { new thread(this).start(); log.d("ook" , "created"); } @override public void surfacechanged(surfaceholder surfaceholder, int i, int i1, int i2) { log.d("ook" , "changed"); } @override public void surfacedestroyed(surfaceholder surfaceholder) { isrunning = false; try { thread.sleep(500); } catch (interruptedexception e) { e.printstacktrace(); } } @override public boolean ontouchevent(motionevent event) { int action = event.getaction(); int rawx = (int) event.getx(); switch (action) { case motionevent.action_down: lastx = rawx; break; case motionevent.action_move: int offsetx = rawx - lastx; if (xpredata.size() == 0 && offset > 0) { offset = 0; canscrollright = false; } if (xlastdata.size() == 0 && offset < 0) { offset = 0; canscrollleft = false; } offset = offset + offsetx; if (offset > xaveragevalue && canscrollright) { offset = offset % xaveragevalue; xrawdata.addfirst(xpredata.pollfirst()); yrawdata.addfirst(ypredata.pollfirst()); xlastdata.addfirst(xrawdata.removelast()); ylastdata.addfirst(yrawdata.removelast()); canscrollleft = true; } if (offset < -xaveragevalue && canscrollleft) { offset = offset % xaveragevalue; xrawdata.addlast(xlastdata.pollfirst()); yrawdata.addlast(ylastdata.pollfirst()); xpredata.addfirst(xrawdata.removefirst()); ypredata.addfirst(yrawdata.removefirst()); canscrollright = true; } lastx = rawx; break; case motionevent.action_up: break; } return true; } private point[] getpoints() { point[] points = new point[yrawdata.size()]; for (int i = 0 ; i < yrawdata.size() ; i++) { int ph = bheight - (int)(bheight * (yrawdata.get(i) / maxvalue)); points[i] = new point(xlist.get(i) + offset , ph + margintop); } return points; } public void setdata(linkedlist<double> yrawdata , linkedlist<string> xrawdata , int maxvalue , int averagevalue) { this.maxvalue = maxvalue; this.averagevalue = averagevalue; this.mpoints = new point[yrawdata.size()]; this.yrawdata = yrawdata; this.xrawdata = xrawdata; this.spacingheight = maxvalue / averagevalue; } private int dip2px(float dpvalue) { return (int) (dpvalue * dm.density + 0.5f); } }
mainactivity代码:
public class mainactivity extends activity { linkedlist<double> ylist; linkedlist<string> xrawdata; chartview chartview; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main_activity); chartview = (chartview) findviewbyid(r.id.chartview); ylist = new linkedlist<>(); ylist.add(2.203); ylist.add(4.05); ylist.add(6.60); ylist.add(3.08); ylist.add(4.32); ylist.add(2.0); ylist.add(5.0); xrawdata = new linkedlist<>(); xrawdata.add("05-19"); xrawdata.add("05-20"); xrawdata.add("05-21"); xrawdata.add("05-22"); xrawdata.add("05-23"); xrawdata.add("05-24"); xrawdata.add("05-25"); chartview.setdata(ylist , xrawdata , 8 , 2); } }
此例页面布局比较简单,就是在主页面布局中添加一个自定义的chartview即可,这里不再贴出。可能写得有点仓促,如果不妥之处,请大家批评指正,谢谢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Android实现横向滑动卡片效果