热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android版的股票行情K线图开发

这篇文章主要介绍了Android版的股票行情K线图开发,感兴趣的小伙伴们可以参考一下

现在在手上的是一个证券资讯类型的app,其中有涉及到股票行情界面,行情中有K线图等,看到网上很多人在求这方面的资料,所以我特地写了一个demo在此处给大家分享一下。

下面是做出来的效果图:

背景图是利用canvas先画出一个矩形,然后再画几根虚线,均线图是通过path来绘制的,总之图的绘制是很简单的,我就不在这里作介绍了,大家可以去github下载源码看看。涉及到均线、最高价、最低价、收盘价、开盘价的概念大家可以百度一下。

我再这里要介绍的是计算问题:

大家可以看到分时图、日K、月K的左边的成交价格都是不一样的,而我们的k线都是通过这个价格来绘制的,也就是说价格是时刻变动,那么我们的k线绘制也是变动的。假设我们要计算分时图中价格为25.69的那一分钟应该如何画,画在屏幕中的哪一个位置,那么这个应该怎么画呢,价格是变动的,画的位置也是变动的,但是有一点我们屏幕的大小是不变的。所以我们可以通过背景图的高度来计算某个价格的线图应该从哪个地方开始画。我们可以计算出一个像素点对应多少个价格,分析图如下:

价格和像素形成个一个比例计算是:double   heightScale = (endY - startY)/(highPrice - lowPrice);

所以价格25.69应该是画在mStartY = (float) (startY+ (highPrice - 25.69) * heightScale);

这个明白了之后其他的原理都是一样的,我就不介绍了,下面是部分代码:

@Override 
  protected void drawKChatBackGround() { 
    Rect dirty = new Rect(left, kChartTop, right, KChartbottom); 
    // 画背景图的矩形 
    mCanvas.drawRect(dirty, LineGrayPaint); 
    PathEffect effects = new DashPathEffect(new float[] { 5, 5, 5, 5 }, 1); 
    LineGrayPaint.setPathEffect(effects); 
    Path path = new Path(); 
    int y = kChartTop + 15; 
    // 画上面的虚线 
    path.moveTo(left, y ); 
    path.lineTo(right, y ); 
    String text = getPriceText(highPrice); 
    int textHeight = (int) (textGrayPaint.descent() - textGrayPaint.ascent()); 
    mCanvas.drawText(text,left - textGrayPaint.measureText(text) - 5,y + textHeight/2 ,textGrayPaint); 
    double max = highPrice - lowPrice; 
    if (max > 10){ 
      // 分成四等分 
      // 画中间的三根虚线 
      int n = 4; 
      double sper = (highPrice - lowPrice) / 4;// 每一等分代表的价格 
      for(int i=1;i 0; i--) { 
      int x = left + perWidth * i; 
      path.moveTo(x, kChartTop); 
      path.lineTo(x, KChartbottom); 
      perXPoint[i - 1] = x; 
    } 
    mCanvas.drawPath(path, LineGrayPaint); 
  } 

@Override 
  protected void drawMAChart() { 
    // 画均线 
    Path path5 = new Path(); 
    Path path10 = new Path(); 
    Path path20 = new Path(); 
    double heightScale = (KChartbottom - kChartTop)/(highPrice - lowPrice); 
    int maStart = left; 
    float maStartY; 
    path5.moveTo(maStart, (float) (kChartTop + (highPrice - infos.get(0).getMaValue5()) * heightScale)); 
    path10.moveTo(maStart, (float) (kChartTop + (highPrice - infos.get(0).getMaValue10()) * heightScale)); 
    path20.moveTo(maStart, (float) (kChartTop + (highPrice - infos.get(0).getMaValue20()) * heightScale)); 
     
    for(SingleStockInfo info:infos){ 
      maStart += per * perHalf;// 每一天实际所占的数据是4/6,左右边距各1/6  
      maStartY = (float) (kChartTop + (highPrice - info.getMaValue5()) * heightScale); 
      path5.lineTo(maStart, maStartY); 
      maStartY = (float) (kChartTop + (highPrice - info.getMaValue10()) * heightScale); 
      path10.lineTo(maStart, maStartY); 
      maStartY = (float) (kChartTop + (highPrice - info.getMaValue20()) * heightScale); 
      path20.lineTo(maStart, maStartY); 
      maStart += per * perHalf; 
    } 
     
    Paint paint = new Paint(); 
    paint.setColor(Color.BLUE); 
    paint.setAntiAlias(true); 
    paint.setStrokeWidth(2); 
    paint.setStyle(Style.STROKE); 
    mCanvas.drawPath(path5, paint); 
    paint.setColor(Color.MAGENTA); 
    mCanvas.drawPath(path10, paint); 
    paint.setColor(Color.GREEN); 
    mCanvas.drawPath(path20, paint); 
  }
/** 
   * 下面的柱形图 
   */ 
  @Override 
  protected void drawPillarsChart(int flag) { 
    LineGrayPaint.setPathEffect(null); 
    Rect dirty = new Rect(left, pillarsChartTop, right, pillarsChartbottom); 
    // 画背景图的矩形 
    mCanvas.drawRect(dirty, LineGrayPaint); 
     
    int y = pillarsChartTop + (pillarsChartbottom - pillarsChartTop)/2; 
    mCanvas.drawLine(left,y,right, y, LineGrayPaint); 
     
    // 中间的值 
    String totalCount = getPriceText(maxCount/2/10000); 
    float maginLeft = left - textGrayPaint.measureText(totalCount)- 5; 
    mCanvas.drawText(totalCount, maginLeft, y,textGrayPaint); 
    // 上面的值 
    totalCount = getPriceText(maxCount/10000); 
    maginLeft = left - textGrayPaint.measureText(totalCount)- 5; 
    mCanvas.drawText(totalCount, maginLeft, pillarsChartTop,textGrayPaint); 
    // 下面的值 
    totalCount = "万手"; 
    maginLeft = left - textGrayPaint.measureText(totalCount) - 5; 
    mCanvas.drawText(totalCount, maginLeft, pillarsChartbottom,textGrayPaint); 
    int pStart = left; 
    float pStartY; 
    double heightScale = (pillarsChartbottom - pillarsChartTop)/maxCount; 
    Paint paint = new Paint(); 
    paint.setAntiAlias(true); 
    paint.setStyle(Paint.Style.FILL); 
    if (flag == StockService.FLAG){ 
      for(MinuteInfo info:minuteInfos){ 
        pStart += per * per16;// 每一天实际所占的数据是4/6,加上1/6 
        pStartY = (float) (pillarsChartTop + (maxCount - info.getVolume()) * heightScale); 
        dirty = new Rect(pStart, (int) pStartY, (int) (pStart + per * per46), pillarsChartbottom-2); 
        paint.setColor(info.getColor()); 
        // 画背景图的矩形 
        mCanvas.drawRect(dirty, paint); 
        pStart += per * per56;// 右边的间距 5/6 
      } 
    }else{ 
      for(SingleStockInfo info:infos){ 
        pStart += per * per16;// 每一天实际所占的数据是4/6,加上1/6 
        pStartY = (float) (pillarsChartTop + (maxCount - info.getTotalCount()) * heightScale); 
        dirty = new Rect(pStart, (int) pStartY, (int) (pStart + per * per46), pillarsChartbottom-2); 
        paint.setColor(info.getColor()); 
        // 画背景图的矩形 
        mCanvas.drawRect(dirty, paint); 
        pStart += per * per56;// 右边的间距 5/6 
      } 
    } 
  } 
/** 
   * 分时图 
   */ 
  @Override 
  public void drawHoursChart(){ 
    double heightScale = (KChartbottom - kChartTop)/(highPrice - lowPrice); 
    int cLeft = left; 
    int cTop = 0; 
    Path path = new Path(); 
    path.moveTo(cLeft, KChartbottom-2); 
    int position = 0; 
    int perPointX = perXPoint[position];// 记录第一条垂直虚线的x坐标 
    for(MinuteInfo info:minuteInfos){ 
      cLeft += per * per16; 
      cTop = (int) (kChartTop + (highPrice - info.getNow()) * heightScale); 
      path.lineTo(cLeft + per * per26, cTop); 
      if (cLeft >= perPointX){ 
        // 恰好画到第一条垂直虚线的地方,需要画下面的时间 
        String text = KChartUtil.getMinute(info.getMinute()); 
        float textWidth = textGrayPaint.measureText(text); 
        int textHeight = (int) (textGrayPaint.descent()- textGrayPaint.ascent()); 
        mCanvas.drawText(text, perPointX - textWidth/2, KChartbottom + textHeight, textGrayPaint); 
        if (!(position == perXPoint.length-1)){ 
          Log.e(TAG, perPointX+"----------"+info.getMinute()+"---"+text); 
          perPointX = perXPoint[++position]; 
        } 
      } 
      cLeft += per * per56;// 右边的间距 5/6 
    } 
    path.lineTo(cLeft, KChartbottom-2); 
    Paint LinePaint = new Paint(); 
    LinePaint.setColor(Color.BLUE); 
    LinePaint.setAntiAlias(true); 
    LinePaint.setStrokeWidth(1); 
    LinePaint.setStyle(Style.STROKE); 
//   LinePaint.setStyle(Style.STROKE); 
    mCanvas.drawPath(path, LinePaint); 
    LinePaint.setAlpha(50); 
    LinePaint.setStyle(Style.FILL); 
    mCanvas.drawPath(path, LinePaint); 
  } 

新年伊始,中国股市走出世界罕见,前无古人后无来者的极端行情,股市有风险,投资需谨慎。
这句话是题外话了,重点还是希望对大家学习Android程序设计有所帮助。


推荐阅读
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 在维护公司项目时,发现按下手机的某个物理按键后会激活相应的服务,并在屏幕上模拟点击特定坐标点。本文详细介绍了如何使用ADB Shell Input命令来模拟各种输入事件,包括滑动、按键和点击等。 ... [详细]
  • 本文深入探讨了 com.example.android.sunshine.data.TestUtilities 中 validateThenCloseCursor() 方法的使用方法及其代码示例,旨在帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
  • 百度搜索结果链接提取工具 UrlGetter V1.43
    该工具专为获取百度搜索引擎的结果页面中的网址链接而设计,能够解析并转换为原始URL。通过正则表达式匹配技术,精准提取网页链接,并提供详细的使用说明和下载资源。 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 2023 ARM嵌入式系统全国技术巡讲旨在分享ARM公司在半导体知识产权(IP)领域的最新进展。作为全球领先的IP提供商,ARM在嵌入式处理器市场占据主导地位,其产品广泛应用于90%以上的嵌入式设备中。此次巡讲将邀请来自ARM、飞思卡尔以及华清远见教育集团的行业专家,共同探讨当前嵌入式系统的前沿技术和应用。 ... [详细]
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
author-avatar
mobiledu2502876293
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有