关闭

股票应用开发——图表的绘制(三)

标签: android股票
264人阅读 评论(0) 收藏 举报
分类:

        大家好,又一次和大家见面了!最近在写关于股票应用开发过程中的新的体会,希望对大家有所帮助,让大家不要向我一样,少走一些弯路。还用就是最近在更新这个系列的博客,怕到后面忙起来或者不想写了就落下了!

       今天主要说的是图表的绘制,当然你需要继承View,也就是现在一搜一大把的自定义View。我的整体思路是这样的:

       首先需要定义图表的基类,在基类内需要定义或者绘制一些共性的东西,如图表的大小,背景色,字体,坐标轴等等信息;

       然后就是继承图表的基类进行图形的绘制;

下面先说一下图表实体类的基类:

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、基类的定义:Chart.java

       基类解决的是共性问题,首先我们需要初始化一些图表的设置,确定图表的大小,颜色,字体等;其次就是在onDraw()方法内进行相关的绘制工作,如图表的边框,网格线等;最后就是定义图表点击的回调函数;

下面是代码示例:

二、绘制图表:CandleChart.java

       定义CandleChart.java继承Chart.java并实现Chart内部定义的接口:

       重写onDraw(Canvas canvas)方法,在方法内部,对K线图,成交量图,MACD图,KDJ图,绘制坐标轴以及刻度值,绘制十字线以及信息详情框;

       下面说一下技术难点:

A.    屏幕的手势设置:

思路参考:如下思维导图


关于手势实现思路:

首先是拖动十字线的实现,在实现的过程中是通过调用postInvalidate()去刷新View;

其次是拖动图表的实现,在实现过程中首先是隐藏十字线和信息显示框,然后判断移动距离是否满足最小移动距离,在这里是通过定义一个变量表示图表显示的起始位置来实现图表的移动的;

       最后是实现图表的缩放,实现的思路是首先计算手指触屏的初始位置,计算两手指之间的距离,当手指移动之后计算此时手指之间的距离,如果当前手指之间的距离大于初始时刻手指之间的距离,就对图表进行放大,反之缩小;还有需要注意的是在计算两手指之间的距离的时候,也就是在设置触摸模式之前需要判断当前屏幕有几个触摸点,否则会报异常(pointer index out of range);

B.图形的绘制:

a>无论是在绘制蜡烛图还是在绘制其他图形的时候首先需要将数据转化成屏幕上对应的像素,也就是转换的比率rate = getLowerChartHeight() / (max - 0),然后需要注意绘制每条数据的坐标位置,尤其是绘制上下两个关联的图表时,一定要注意坐标的一致性;

b>绘制MACD图表:

       为什么要单独说一下绘制MACD的图表呢?因为该图表存在y = 0 这条轴线,当然如果你不希望绘制的图形有固定的X轴,则可以不考虑这个问题;

       但是若没有固定的y = 0这条轴线,那么可能会出现当你的图表进行缩放的时候会在画布中移动,也就是X轴不固定;

       若存在这条固定的轴线,会出现该轴线上下两侧的缩放比例不一致的问题;

------------------------------------------------------------------------------------------------------------------

就说这么多吧,下面是代码示例:

绘制蜡烛图代码:

   /**
     * 绘制蜡烛图,也就是K线图
     */
    private void drawUpperRegion() {
//        LogUtil.i("tag", "CandleChart..drawUpperRegion" + getTime());
        //绘制蜡烛图
        Paint redPaint = new Paint();
        redPaint.setColor(Color.RED);
        Paint greenPaint = new Paint();
        greenPaint.setColor(Color.GREEN);

        int width = getWidth();//屏幕的宽度
        //设置Candle的宽度
        mCandleWidth = (width - 4) / 10.0f * 10.0f / mShowDataNum;
        /**计算蜡烛图每一个矩形的高度比例*/
        double rate = (getUperChartHeight() - 60) / (mMaxPrice - mMinPrice);

        for (int i = 0; i < mShowDataNum && mDataStartIndext + i < mList.size(); i++) {
            StockInfo info = mList.get(mDataStartIndext + i);

            /**计算每一天股票的价格所对应的像素*/
            float open = (float) ((mMaxPrice - info.getOpen()) * rate + DEFAULT_AXIS_LABLE_SIZE + 4);
            float close = (float) ((mMaxPrice - info.getClose()) * rate + DEFAULT_AXIS_LABLE_SIZE + 4);
            float high = (float) ((mMaxPrice - info.getHigh()) * rate + DEFAULT_AXIS_LABLE_SIZE + 4);
            float low = (float) ((mMaxPrice - info.getLow()) * rate + DEFAULT_AXIS_LABLE_SIZE + 4);

            float right = (float) (3 + mCandleWidth * (i + 1));
            float left = (float) (3 + mCandleWidth * i);
            //计算绘制每个蜡烛的开始X坐标
            float startX = (float) (3 + mCandleWidth * i + (mCandleWidth - 1) / 2);
            /**设置蜡烛图的颜色*/
            if (open < close) {
                canvas.drawRect(left, open, right, close, greenPaint);
//                LogUtil.i("tag","开盘价小于收盘价:left"+left+";close:"+close+";right:"+right+";open:"+open);
                canvas.drawLine(startX, high, startX, low, greenPaint);
            } else if (open == close) {
                canvas.drawLine(left, open, right, open, redPaint);
//                LogUtil.i("tag","开盘价=收盘价:left"+left+";open:"+open+";right:"+right+";open:"+open);
                canvas.drawLine(startX, high, startX, low, redPaint);
            } else {
                canvas.drawRect(left, close, right, open, redPaint);
//                LogUtil.i("tag","开盘价大于收盘价:left"+left+";open:"+open+";right:"+right+";close:"+close);
                canvas.drawLine(startX, high, startX, low, redPaint);
            }
        }

       
    }
绘制MACD图代码片段:

   /**
     * 绘制MACD指标图形
     */

    private void drawMACDChart() {

        float middle = LOWER_CHART_TOP + getLowerChartHeight() / 2;//获取下部绘图区域的中间位置
        mCandleWidth = (getWidth() - 4) / 10.0f * 10.0f / mShowDataNum;

        Paint linePaint = new Paint();//绘制曲线
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(2);

        Paint textPaint = new Paint();
        textPaint.setColor(DEFAULT_AXIS_X_LABLE_COLOR);
        textPaint.setTextSize(DEFAULT_AXIS_LABLE_SIZE);

        /**初始化集合数据*/
        MACD = mMacdData.getMACD();//集合不要忘记添加数据!
        DEA = mMacdData.getDEA();
        DIF = mMacdData.getDIF();

        if (!MACD.isEmpty() && !DEA.isEmpty() && !DIF.isEmpty()) {
            double low = DEA.get(mDataStartIndext);//刻度最小值
            double high = low;//刻度最大值
            double upRate = 0.0;//0刻度线之上绘图比例
            double downRate = 0.0;//0刻度线之下绘图比例
            double lineRate = 0.0;//
            for (int i = mDataStartIndext; i < mDataStartIndext + mShowDataNum && i < MACD.size(); i++) {
                low = low < MACD.get(i) ? low : MACD.get(i);
                low = low < DEA.get(i) ? low : DEA.get(i);
                low = low < DIF.get(i) ? low : DIF.get(i);

                high = high > MACD.get(i) ? high : MACD.get(i);
                high = high > DEA.get(i) ? high : DEA.get(i);
                high = high > DIF.get(i) ? high : DIF.get(i);
            }

            upRate = (getLowerChartHeight() / 2 - 4) / (high - 0);//计算上部比例
            downRate = (getLowerChartHeight() / 2 - 4) / Math.abs(low - 0);//计算下部比例
            lineRate = getLowerChartHeight() / (high - low);
            Paint redP = new Paint();
            redP.setColor(Color.RED);
            Paint greenP = new Paint();
            greenP.setColor(Color.GREEN);

            //两条曲线
            float dea = 0.0f;
            float dif = 0.0f;
            //绘制MACD图形
            for (int i = mDataStartIndext; i < mDataStartIndext + mShowDataNum
                    && i < MACD.size(); i++) {
                //绘制矩形
                //计算绘制每个蜡烛的开始X坐标
                float value = MACD.get(i);

                //计算绘制每个蜡烛的开始X坐标
                float startX = (float) (3 + mCandleWidth * (i - mDataStartIndext) + (mCandleWidth - 1) / 2);

                if (MACD.get(i) >= 0) {//MACD值大于0绘制在y = 0上方,红色;
                    canvas.drawLine(startX, (float) ((high - value) * upRate) + LOWER_CHART_TOP, startX, middle, redP);
                } else {
                    canvas.drawLine(startX, middle, startX, (float) (middle + Math.abs(value) * downRate), greenP);
                }

                if (i != mDataStartIndext) {

                    linePaint.setColor(Color.YELLOW);
                    canvas.drawLine(3 + (float) mCandleWidth * (i + 1 - mDataStartIndext) + (float) mCandleWidth / 2,
                            (float) ((high - DEA.get(i)) * lineRate) + LOWER_CHART_TOP,
                            3 + (float) mCandleWidth * (i - mDataStartIndext) + (float) mCandleWidth / 2,
                            dea,
                            linePaint);

                    linePaint.setColor(Color.RED);
                    canvas.drawLine(3 + (float) mCandleWidth * (i + 1 - mDataStartIndext) + (float) mCandleWidth / 2,
                            (float) ((high - DIF.get(i)) * lineRate) + LOWER_CHART_TOP,
                            3 + (float) mCandleWidth * (i - mDataStartIndext)
                                    + (float) mCandleWidth / 2, dif, linePaint);
                }
                dea = (float) ((high - DEA.get(i)) * lineRate) + LOWER_CHART_TOP;
                dif = (float) ((high - DIF.get(i)) * lineRate) + LOWER_CHART_TOP;

            }
            canvas.drawText(ValueFormater.format(high) + "", 2,
                    LOWER_CHART_TOP + DEFAULT_AXIS_LABLE_SIZE - 2, textPaint);
            canvas.drawText(ValueFormater.format((high + low) / 2) + "", 2,
                    LOWER_CHART_TOP + getLowerChartHeight() / 2 + DEFAULT_AXIS_LABLE_SIZE, textPaint);
            canvas.drawText(ValueFormater.format(low) + "", 2,
                    LOWER_CHART_TOP + getLowerChartHeight(),
                    textPaint);
        }

    }

其他的指标绘制方法类似,就不在贴代码了。





0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5532次
    • 积分:239
    • 等级:
    • 排名:千里之外
    • 原创:17篇
    • 转载:0篇
    • 译文:2篇
    • 评论:1条