基于AChartEngine绘制股票走势图----分时图一(走势柱状)


概述(项目地址:https://github.com/JiangYueA/android_aps

使用AChartEngine实现股票分时、五日、k线图,分时图主要有均线,时价的走势和成交量的柱状图,可以使用AChartEngine的CombinedTemperatureChart这个图表类型作为demo,主要是混合Line,Bar这两种图;后期可以加入手势移动显示xy坐标值,实现思路是在GraphicView里面监听onTouchEvent,传递到各个Chart类型的图里面去;
下面先贴上最终要实现的效果图:
这里写图片描述


第一阶段先从简单的分时图开始,主要要考虑的是柱状图和线图数据的处理,AChartEngine支持多图型绘制在同一面板,这样我通过数据的处理把时价线,均价线,成交量柱状图画在同一画布上;

        //数据处理
        XYSeries series01 = new XYSeries("Line", 0);//均线
        XYSeries series02 = new XYSeries("Line", 0);//时实走势
        XYSeries series03 = new XYSeries("RangeBar", 0);//成交量柱状图
        //极值
        double minValue = 1000000000;
        double maxValue = -1000000000;
        double minTradeValue = 1000000000;
        double maxTradeValue = -1000000000;
        //数据填装
        for (int i = 0, size = minuteSize; i < size; i++) {
            series01.add(i, minuteLine.get(i).cjprice);
            series02.add(i, minuteLine.get(i).avprice);
            //求最小值
            if (minValue > minuteLine.get(i).cjprice) {
                minValue = minuteLine.get(i).cjprice;
            }
            if (minValue > minuteLine.get(i).avprice) {
                minValue = minuteLine.get(i).avprice;
            }
            if (minTradeValue > minuteLine.get(i).cjnum) {
                minTradeValue = minuteLine.get(i).cjnum;
            }
            //求最大值
            if (maxValue < minuteLine.get(i).cjprice) {
                maxValue = minuteLine.get(i).cjprice;
            }
            if (maxValue < minuteLine.get(i).avprice) {
                maxValue = minuteLine.get(i).avprice;
            }
            if (maxTradeValue < minuteLine.get(i).cjnum) {
                maxTradeValue = minuteLine.get(i).cjnum;
            }
        }
        //重新设置极小值,留涨幅空隙
        double temp = maxValue - minValue > minValue ? minValue : maxValue - minValue;
        maxValue = maxValue + (temp) * 0.2;
        minValue = minValue - (temp) * 0.2;
        if (maxValue - entity.shareRtData.dRtPreClose > entity.shareRtData.dRtPreClose - minValue) {
            minValue = entity.shareRtData.dRtPreClose - (maxValue - entity.shareRtData.dRtPreClose) * 5 / 7;
        } else {
            maxValue = entity.shareRtData.dRtPreClose + (entity.shareRtData.dRtPreClose - minValue) * 5 / 7;
        }
        //获取成交量基数
        temp = maxValue - minValue > minValue ? minValue : maxValue - minValue;
        double baseTradeValue = 1 / (maxTradeValue - minTradeValue) * (temp) * (0.4 - 0.1);
        minValue = minValue - (temp) * 0.4;
        //设置成交量柱状图数据
        for (int i = 0, size = entity.shareFsDatas.size(); i < size; i++) {
            series03.add(i, minValue + (entity.shareFsDatas.get(i).dFsVolume - minTradeValue) * baseTradeValue);
        }

均线数据在分钟model的时候已经处理过,AChartEngine绘图有最高最小值,可通过滑分Y轴的数值范围去切割开时价线于成交量柱状图的绘制区间。
解析数据步骤:
- 获取均线和时价线的最大最小值,chart设定y轴的高度,在均线和时价线最大最小值的基础上,留0.4的高度来放置成交量,成交量的值通过与最大最小值的比换算;
- XYSeries值换算坐标点,在XYChart的draw里换算
- 生成的坐标值,传递到对应的图标类型LineChart,BarChart绘制,BarChart有两个坐标,左右,同时需要根据间隔系数获取间隔
坐标换算代码:

synchronized (series) {
        SortedMap<Double, Double> range = series.getRange(minX[scale], maxX[scale],
            seriesRenderer.isDisplayBoundingPoints());
        int startIndex = -1;

        for (Entry<Double, Double> value : range.entrySet()) {
          double xValue = value.getKey();
          double yValue = value.getValue();
          if (startIndex < 0 && (!isNullValue(yValue) || isRenderNullValues())) {
            startIndex = series.getIndexForKey(xValue);
          }

          // points.add((float) (left + xPixelsPerUnit[scale]
          // * (value.getKey().floatValue() - minX[scale])));
          // points.add((float) (bottom - yPixelsPerUnit[scale]
          // * (value.getValue().floatValue() - minY[scale])));
          values.add(value.getKey());
          values.add(value.getValue());

          if (!isNullValue(yValue)) {
            points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));
            points.add((float) (bottom - yPixelsPerUnit[scale] * (yValue - minY[scale])));
          } else if (isRenderNullValues()) {
            points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));
            points.add((float) (bottom - yPixelsPerUnit[scale] * (-minY[scale])));
          } else {
            if (points.size() > 0) {
              drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or,
                  startIndex);
              ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(points, values,
                  yAxisValue, i, startIndex);
              clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));
              points.clear();
              values.clear();
              startIndex = -1;
            }
            clickableArea.add(null);
          }
        }

        int count = series.getAnnotationCount();
        if (count > 0) {
          paint.setColor(seriesRenderer.getAnnotationsColor());
          paint.setTextSize(seriesRenderer.getAnnotationsTextSize());
          paint.setTextAlign(seriesRenderer.getAnnotationsTextAlign());
          Rect bound = new Rect();
          for (int j = 0; j < count; j++) {
            float xS = (float) (left + xPixelsPerUnit[scale]
                * (series.getAnnotationX(j) - minX[scale]));
            float yS = (float) (bottom - yPixelsPerUnit[scale]
                * (series.getAnnotationY(j) - minY[scale]));
            paint.getTextBounds(series.getAnnotationAt(j), 0, series.getAnnotationAt(j).length(),
                bound);
            if (xS < (xS + bound.width()) && yS < canvas.getHeight()) {
              drawString(canvas, series.getAnnotationAt(j), xS, yS, paint);
            }
          }
        }

        if (points.size() > 0) {
          drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or, startIndex);
          ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(points, values,
              yAxisValue, i, startIndex);
          clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));
        }
      }
    }

最后得到的List points既是坐标集合,(ps,在遇到NaN或无效值是会断开计算直接绘制,这种情况,绘制bar会有误差);

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值