数码控科技猎奇Iphone动漫星座游戏电竞lolcosplay王者荣耀攻略allcnewsBLOGNEWSBLOGASKBLOGBLOGZSK全部技术问答问答技术问答it问答代码软件新闻开发博客电脑/网络手机/数码笔记本电脑互联网操作系统软件硬件编程开发360产品资源分享电脑知识文档中心IT全部全部分类全部分类技术牛文全部分类教程最新网页制作cms教程平面设计媒体动画操作系统网站运营网络安全服务器教程数据库工具网络安全软件教学vbscript正则表达式javascript批处理更多»编程更新教程更新游戏更新allitnewsJava新闻网络医疗信息化安全创业站长电商科技访谈域名会议专栏创业动态融资创投创业学院 / 产品经理创业公司人物访谈营销开发数据库服务器系统虚拟化云计算嵌入式移动开发作业作业1常见软件all电脑网络手机数码生活游戏体育运动明星影音休闲爱好文化艺术社会民生教育科学医疗健康金融管理情感社交地区其他电脑互联网软件硬件编程开发360相关产品手机平板其他电子产品摄影器材360硬件通讯智能设备购物时尚生活常识美容塑身服装服饰出行旅游交通汽车购房置业家居装修美食烹饪单机电脑游戏网页游戏电视游戏桌游棋牌游戏手机游戏小游戏掌机游戏客户端游戏集体游戏其他游戏体育赛事篮球足球其他运动球类运动赛车健身运动运动用品影视娱乐人物音乐动漫摄影摄像收藏宠物幽默搞笑起名花鸟鱼虫茶艺彩票星座占卜书画美术舞蹈小说图书器乐声乐小品相声戏剧戏曲手工艺品历史话题时事政治就业职场军事国防节日风俗法律法规宗教礼仪礼节自然灾害360维权社会人物升学入学人文社科外语资格考试公务员留学出国家庭教育学习方法语文物理生物工程学农业数学化学健康知识心理健康孕育早教内科外科妇产科儿科皮肤科五官科男科整形中医药品传染科其他疾病医院两性肿瘤科创业投资企业管理财务税务银行股票金融理财基金债券保险贸易商务文书国民经济爱情婚姻家庭烦恼北京上海重庆天津黑龙江吉林辽宁河北内蒙古山西陕西宁夏甘肃青海新疆西藏四川贵州云南河南湖北湖南山东江苏浙江安徽江西福建广东广西海南香港澳门台湾海外地区

Android绘制动态折线图

来源:脚本之家  责任编辑:小易  

所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果。基于这个效果,这里使用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自定义控件实现折线图
  • android hellochart开源库图表之折线图的实例代码
  • android mpandroidchart开源库图表之折线图的实例代码
  • android自定义view简易折线图控件(二)
  • 详解android图表 mpandroidchart折线图
  • android自定义view实现折线图效果
  • android开发之天气趋势折线图
  • mpandroidchart开源图表库的使用介绍之饼状图、折线图和柱状图
  • android 通过jni返回mat数据类型方法
  • android 实现不同字体颜色的textview实现代码
  • android基于recyclerview实现高亮搜索列表
  • android中fragment的解析和使用详解
  • android中底部菜单被输入法顶上去的解决方案
  • android开发之activity的生命周期详解
  • 深入探讨unit testing in android
  • android 偷拍功能实现(手机关闭依然拍照)详解及实例代码
  • android之高德地图定位sdk集成及地图功能实现
  • android 面试精华题目总结
  • 免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved