当前位置: 移动技术网 > IT编程>移动开发>Android > Android绘制动态折线图

Android绘制动态折线图

2019年07月30日  | 移动技术网IT编程  | 我要评论

尽在不言中txt,李维嘉多大了,足球小窝秦协

所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果。基于这个效果,这里使用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即可,这里不再贴出。可能写得有点仓促,如果不妥之处,请大家批评指正,谢谢!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网