K线图和分时图


代码仓库用~

package com.cxzapp.stamp.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.chengxuanzhang.lib.util.StringUtil;
import com.cxzapp.stamp.modules.user.UserModels;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * Created by softrice on 15/10/18.
 */
public class OnTimeChartView extends View {

    /**
     * color
     */
    int chartBgColor = 0xFF272727;//图标背景色
    int upTextColor = Color.RED;//上升时text的颜色
    int defaultTextColor = Color.WHITE;//默认字体颜色
    int downTextColor = Color.GREEN;//下降的时候text的颜色
    int bordColor = 0xFF333333;//图标边框颜色
    int charDivideLineColor = 0xFF333333;//图表分割线颜色
    int charBaseDivideLineColor = 0xFF432925;//开盘价分割线颜色
    int pathLineColor = 0xFFBFBFBF;//折线的颜色
    int hintLineColor = 0xFFFF423D;//点击时 提示线的颜色
    /**
     * size
     */
    int viewHeight;//view 的高度
    int viewPadding = 10;//图表边距
    int textSize = 12;//字体大小 单位sp
    int chartHeight;//图表高度
    int leftTextLenght;//左边数字的长度
    int rightTextLenght;//右边数字的长度
    int textHigh;//text高度
    int chartWidth;//图表的宽度
    //chart 的上下左右
    int top;
    int left;
    int right;
    int bottom;
    /**
     * paint
     */
    Paint textPaint;
    Paint linePaint;

    /**
     * touch 部分
     */
    float currentX;//当前点击的x
    float currentY;//当前点击的y
    long downTime;//手指点击下的时间 毫秒
    int intervalTime = 300;//时间间隔 单位 毫秒 点击抬起时间小于该值触发点击事件
    TouchListener touchListener;



    /**
     * data
     */
    List stampChartList;
    double maxValue = 2999.01;
    double minValue = 1320.89;
    double openValue;
    List xTitle;
    final int YValueNum = 3;//从开盘价开始 往上 和 往下 的刻度数目

    /**
     * time
     */
    Calendar c = Calendar.getInstance();
    int startTime;
    int endTime;
    int afternoonTime;


    public OnTimeChartView(Context context) {
        super(context);
        init();
    }


    public OnTimeChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public OnTimeChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setBackgroundColor(chartBgColor);
        //获取今天的涨跌图 早上9:30 晚上15:00
        c.set(Calendar.HOUR_OF_DAY, 9);
        c.set(Calendar.MINUTE, 30);
        c.set(Calendar.SECOND, 0);
        startTime = (int) (c.getTime().getTime() / 1000);
        c.set(Calendar.HOUR_OF_DAY, 15);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        endTime = (int) (c.getTime().getTime() / 1000);

        c.set(Calendar.HOUR_OF_DAY, 13);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);

        afternoonTime = (int) (c.getTime().getTime() / 1000);

        textPaint = new Paint();
        linePaint = new Paint();
        textPaint.setAntiAlias(true);
        linePaint.setAntiAlias(true);
        textPaint.setTextSize(sp2px(textSize));

        leftTextLenght = (int) (textPaint.measureText("88888.88") + 0.5);
        rightTextLenght = (int) (textPaint.measureText("-10.00") + 0.5);
        textHigh = getTextHight(textPaint);
        chartHeight = 13 * textHigh;
        viewHeight = chartHeight + 2 * textHigh + 2 * viewPadding;

        xTitle = new ArrayList<>();
        xTitle.add("09:30");
        xTitle.add("10:30");
        xTitle.add("11:30/13:00");
        xTitle.add("14:00");
        xTitle.add("15:00");
    }

    private int getTextHight(Paint paint) {
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        return (int) (fontMetrics.bottom - fontMetrics.top + 0.5f);
    }

    /**
     * 长度只能match
     * 高度只可wrap 和 match
     */

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, viewHeight);
        chartWidth = getWidth() - 2 * viewPadding - leftTextLenght - rightTextLenght;
        top = textHigh + viewPadding;
        left = viewPadding + leftTextLenght;
        right = viewPadding + leftTextLenght + chartWidth;
        bottom = textHigh + viewPadding + chartHeight;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //  super.onDraw(canvas);
        drawY(canvas);
        drawX(canvas);
        drawBorder(canvas);
        drawPathLine(canvas);
        drawHint(canvas);
    }

    private void drawHint(Canvas canvas) {
        if (currentX == -1 || currentY == -1 || stampChartList == null || stampChartList.size() == 0)
            return;
        if (!(currentX <= right && currentX >= left && currentY >= top && currentY <= bottom))
            return;
        DecimalFormat df = new DecimalFormat("0.00");
        linePaint.setStrokeWidth(1);
        linePaint.setColor(hintLineColor);
        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.CENTER);
        int position = getDataNum();
        if (position != -1) {
            UserModels.StampChart chart = stampChartList.get(position);
            canvas.drawLine(currentX, top, currentX, bottom, linePaint);
            int y = getPriceY(chart.CurPrice);
            canvas.drawLine(left, y, right, y, linePaint);
            canvas.drawText(StringUtil.formatDate(chart.update_time, "HH:mm"), currentX, viewHeight - viewPadding - textHigh, textPaint);
            if (chart.CurPrice >= openValue)
                textPaint.setColor(upTextColor);
            else
                textPaint.setColor(downTextColor);
            textPaint.setTextAlign(Paint.Align.LEFT);
            canvas.drawText(df.format(chart.CurPrice), viewPadding, y + getTextBottom(textPaint), textPaint);
            double valuePercent = (chart.CurPrice - openValue) / openValue * 100;

            canvas.drawText(df.format(valuePercent), getWidth() - viewPadding - rightTextLenght, y + getTextBottom(textPaint), textPaint);
            canvas.drawText(df.format(chart.CurPrice), viewPadding, y + getTextBottom(textPaint), textPaint);
        }

    }

    private int getDataNum() {
        for (int i = 0; i < stampChartList.size(); i++) {
            UserModels.StampChart chart = stampChartList.get(i);
            if (chart.CurPrice == 0) continue;
            if (Math.abs(getTimeX(chart.update_time) - currentX) <= 1) {
                return i;
            }
        }
        return -1;
    }

    private void drawPathLine(Canvas canvas) {
        if (stampChartList == null || stampChartList.size() == 0)
            return;
        linePaint.setStrokeWidth(1);
        linePaint.setColor(pathLineColor);
        linePaint.setAntiAlias(true);
        PointF oldF = new PointF(getTimeX(stampChartList.get(0).update_time), getPriceY((float) openValue));
        for (int i = 0; i < stampChartList.size(); i++) {
            UserModels.StampChart tmp = stampChartList.get(i);
            if (tmp.CurPrice < 0.1)
                continue;
            int x = (int) getTimeX(tmp.update_time);
            int y = (int) getPriceY(tmp.CurPrice);
            canvas.drawLine(oldF.x, oldF.y, x, y, linePaint);
            oldF.set(x, y);
        }
    }

    private int getPriceY(float curPrice) {
        return (int) ((maxValue - curPrice) * 1.0 / (maxValue - minValue) * chartHeight + viewPadding + textHigh);
    }

    private int getTimeX(int update_time) {
        if (update_time > afternoonTime) {
            return (int) ((update_time - afternoonTime + 2 * 60 * 60) * 1.0 / (4 * 60 * 60) * (chartWidth) + viewPadding + leftTextLenght);
        } else {
            return (int) ((update_time - startTime) * 1.0 / (4 * 60 * 60) * (chartWidth) + viewPadding + leftTextLenght);
        }
    }


    private void drawBorder(Canvas canvas) {
        linePaint.setStrokeWidth(1);
        linePaint.setColor(bordColor);
        canvas.drawLine(left, top, right, top, linePaint);
        canvas.drawLine(left, bottom, right, bottom, linePaint);
        canvas.drawLine(left, top, left, bottom, linePaint);
        canvas.drawLine(right, top, right, bottom, linePaint);
//        linePaint.setColor(charBaseDivideLineColor);
//        canvas.drawLine(left, (top + bottom) / 2, right, (top + bottom) / 2, linePaint);
        linePaint.setColor(charDivideLineColor);

        int y = chartHeight / YValueNum / 2;
        for (int i = 1; i < YValueNum; i++) {
            canvas.drawLine(left, (top + bottom) / 2 + y * i, right, (top + bottom) / 2 + y * i, linePaint);
            canvas.drawLine(left, (top + bottom) / 2 - y * i, right, (top + bottom) / 2 - y * i, linePaint);
        }
        int x = chartWidth / (xTitle.size() - 1);
        for (int i = 1; i < xTitle.size() - 1; i++) {
            canvas.drawLine(left + i * x, top, left + i * x, bottom, linePaint);
        }

        linePaint.setColor(charBaseDivideLineColor);
        linePaint.setStrokeWidth(2);
        canvas.drawLine(left, (top + bottom) / 2, right, (top + bottom) / 2, linePaint);
    }

    private void drawY(Canvas canvas) {
        double mid = (maxValue + minValue) / 2;
        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.LEFT);
        DecimalFormat df = new DecimalFormat("0.00");
        canvas.drawText(df.format(mid) + "", viewPadding, viewHeight / 2 + getTextBottom(textPaint), textPaint);
        canvas.drawText("0.00", getWidth() - viewPadding - rightTextLenght, viewHeight / 2 + getTextBottom(textPaint), textPaint);
        textPaint.setColor(upTextColor);
        textPaint.setTextAlign(Paint.Align.LEFT);
        for (int i = 1; i <= YValueNum; i++) {
            double value = mid + (maxValue - mid) * i / YValueNum;
            double valuePercent = (value - openValue) / openValue * 100;
            canvas.drawText(df.format(value) + "", viewPadding, viewHeight / 2 - textHigh * 2 * i + getTextBottom(textPaint), textPaint);
            canvas.drawText(df.format(valuePercent), getWidth() - viewPadding - rightTextLenght, viewHeight / 2 - textHigh * 2 * i + getTextBottom(textPaint), textPaint);
        }
        textPaint.setTextAlign(Paint.Align.LEFT);
        textPaint.setColor(downTextColor);
        for (int i = 1; i <= YValueNum; i++) {
            double value = mid - (mid - minValue) * i / YValueNum;
            double valuePercent = (value - openValue) / openValue * 100;
            canvas.drawText(df.format(value) + "", viewPadding, viewHeight / 2 + textHigh * 2 * i + getTextBottom(textPaint), textPaint);
            canvas.drawText(df.format(valuePercent), getWidth() - viewPadding - rightTextLenght, viewHeight / 2 + textHigh * 2 * i + getTextBottom(textPaint), textPaint);
        }


    }

    private int getTextBottom(Paint textPaint) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return (int) fontMetrics.bottom;
    }

    private int getTextTop(Paint textPaint) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return (int) fontMetrics.top;
    }

    private void drawX(Canvas canvas) {
        DecimalFormat df = new DecimalFormat("0.00");
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(defaultTextColor);
        for (int i = 0; i < xTitle.size(); i++) {
            canvas.drawText(xTitle.get(i), viewPadding + leftTextLenght + chartWidth / 4 * i, viewHeight - viewPadding, textPaint);
        }
        textPaint.setTextAlign(Paint.Align.LEFT);
        if (stampChartList != null && stampChartList.size() > 0) {
            double value = stampChartList.get(stampChartList.size() - 1).CurPrice;
            canvas.drawText("最新" + df.format(value), viewPadding + leftTextLenght, viewPadding - getTextTop(textPaint), textPaint);
            int len = (int) textPaint.measureText("最新" + "19488.67");
            double dis = value - openValue;
            double disPercent = dis / openValue * 100;
            if (value < openValue) {
                textPaint.setColor(downTextColor);
                canvas.drawText(" ↓" + df.format(dis) + "(" + df.format(disPercent) + "%)", viewPadding + leftTextLenght + len, viewPadding - getTextTop(textPaint), textPaint);
            } else {
                textPaint.setColor(upTextColor);
                canvas.drawText(" ↑" + df.format(dis) + "(" + df.format(disPercent) + "%)", viewPadding + leftTextLenght + len, viewPadding - getTextTop(textPaint), textPaint);
            }

        } else {
            canvas.drawText("最新-- --(--)", viewPadding + leftTextLenght, viewPadding - getTextTop(textPaint), textPaint);
        }


        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.RIGHT);
        canvas.drawText("涨跌幅(%)", getWidth() - rightTextLenght - viewPadding, viewPadding - getTextTop(textPaint), textPaint);
    }


    public void setStampChartList(List stampChartList) {
        this.stampChartList = stampChartList;
        openValue = 0;
        maxValue = Double.MIN_VALUE;
        minValue = Double.MAX_VALUE;
        if (stampChartList != null) {
            for (int i = 0; i < stampChartList.size(); i++) {
                double curPrice = stampChartList.get(i).CurPrice;
                if (curPrice == 0)
                    continue;
                if (openValue == 0)
                    openValue = curPrice;
                maxValue = maxValue > curPrice ? maxValue : curPrice;
                minValue = minValue < curPrice ? minValue : curPrice;
            }
        } else {
            return;
        }
        double dis = Math.max(maxValue - openValue, openValue - minValue);
        dis += 5;
        maxValue = openValue + dis;
        minValue = openValue - dis;
        this.postInvalidate();

    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        super.dispatchTouchEvent(event);
        Calendar c = Calendar.getInstance();
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                currentX = -1;
                currentY = -1;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                if (judgeDownOrUp(x, y)) {
                    currentX = -1;
                    currentY = -1;
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    currentX = event.getX();
                    currentY = event.getY();
                }
                break;

            case MotionEvent.ACTION_DOWN:
                downTime = c.getTimeInMillis() ;
                currentX = event.getX();
                currentY = event.getY();
                break;
        }
        return true;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                Calendar c = Calendar.getInstance();
                long upTime = c.getTimeInMillis();
                if (upTime - downTime <= intervalTime) {
                    if (touchListener != null) {
                        touchListener.click();
                    }
                } else {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                currentX = -1;
                currentY = -1;
                break;
        }
        postInvalidate();
        return super.onTouchEvent(event);
    }

    private boolean judgeDownOrUp(float x, float y) {
        if (Math.abs(currentX - x) + 10 < Math.abs(currentY - y)) {
            return true;
        } else {
            return false;
        }
    }

    public int sp2px(float spValue) {
        final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    public void setTouchListener(TouchListener touchListener) {
        this.touchListener = touchListener;
    }

    public void setMaxValue(double maxValue) {
        this.maxValue = maxValue;
    }

    public void setMinValue(double minValue) {
        this.minValue = minValue;
    }

    public interface TouchListener {
        void click();
    }
}


package com.cxzapp.stamp.ui;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.chengxuanzhang.lib.util.StringUtil;
import com.cxzapp.stamp.modules.user.UserModels;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.List;

/**
 * Created by softrice on 15/10/19.
 */
public class CandleSticksChartView extends View {

    /**
     * 回调接口
     */
    public interface TouchListener {
        void click();
    }

    /**
     * color
     */
    int MA5Color = Color.WHITE;
    int MA10Color = 0xFFD57123;
    int Ma20Color = 0xFFCB37CA;
    int chartBgColor = 0xFF272727;//图标背景色
    int upTextColor = Color.RED;//上升时text的颜色
    int defaultTextColor = Color.WHITE;//默认字体颜色
    int downTextColor = Color.GREEN;//下降的时候text的颜色
    int bordColor = 0xFF333333;//图标边框颜色
    int charDivideLineColor = 0xFF333333;//图表分割线颜色
    int hintLineColor = 0xFFFF423D;//
    /**
     * size
     */
    int viewHeight;//view 的高度
    int viewPadding = 10;//图表边距
    int textSize = 12;//字体大小 单位sp
    int chartHeight;//图表高度
    int leftTextLenght;//左边数字的长度
    int textHigh;//text高度
    int chartWidth;//图表的宽度
    int defaultStickWidth = 20;
    int stickWidth = defaultStickWidth;// 蜡烛宽度
    int hintBorderWidth;//详情框宽度
    int hintBorderLeftTextWidth;//详情框左边蚊子宽度

    int hintBorderPadding = 10;
    //chart 的上下左右
    int top;
    int left;
    int right;
    int bottom;
    /**
     * paint
     */
    Paint textPaint;
    Paint linePaint;

    /**
     * touch 部分
     */
    float currentX;//当前点击的x
    float currentY;//当前点击的y
    long downTime;//手指点击下的时间
    int intervalTime = 300;//时间间隔 单位 毫秒 点击抬起时间小于该值触发点击事件
    TouchListener touchListener;


    /**
     * data
     */
    List stampInfoList;
    double maxValue = 2000;
    double minValue = 1000;
    final int YValueNum = 7;//Y轴的刻度个数
    int XValueNum = 5;//X轴刻度个数
    int XDay = 10;
    double MA5 = -1, MA10 = -1, MA20 = -1;
    /**
     * time
     */
    Calendar c = Calendar.getInstance();
    int startTime;
    int endTime;


    DecimalFormat df;

    public CandleSticksChartView(Context context) {
        super(context);
        init();
    }

    public CandleSticksChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CandleSticksChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        df = new DecimalFormat("0.00");
        setBackgroundColor(chartBgColor);
        textPaint = new Paint();
        linePaint = new Paint();
        textPaint.setAntiAlias(true);
        linePaint.setAntiAlias(true);
        textPaint.setTextSize(sp2px(textSize));

        leftTextLenght = (int) (textPaint.measureText("88888.88") + 0.5);
        textHigh = getTextHight(textPaint);
        chartHeight = 13 * textHigh;
        viewHeight = chartHeight + 2 * textHigh + 2 * viewPadding;
        hintBorderLeftTextWidth = (int) (textPaint.measureText("日期: ") + 0.5);
        hintBorderWidth = (int) (textPaint.measureText("日期:20150518") + 0.5);


    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        super.dispatchTouchEvent(event);
        Calendar c = Calendar.getInstance();
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                currentX = -1;
                currentY = -1;
                break;
            case MotionEvent.ACTION_MOVE:
                float x = event.getX();
                float y = event.getY();
                if (judgeDownOrUp(x, y)) {
                    currentX = -1;
                    currentY = -1;
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    currentX = event.getX();
                    currentY = event.getY();
                }
                break;

            case MotionEvent.ACTION_DOWN:
                downTime = c.getTimeInMillis();
                currentX = event.getX();
                currentY = event.getY();
                break;
        }
        return true;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                Calendar c = Calendar.getInstance();
                long upTime = c.getTimeInMillis();
                if (upTime - downTime <= intervalTime) {
                    if (touchListener != null) {
                        touchListener.click();
                    }
                } else {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                currentX = -1;
                currentY = -1;
                break;
        }
        postInvalidate();
        return super.onTouchEvent(event);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        drawMA(canvas);
        drawY(canvas);
        drawX(canvas);
        drawBorder(canvas);
        drawCandleSticks(canvas);
        drawHint(canvas);
    }


    private void drawY(Canvas canvas) {
        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.LEFT);
        double disY = (float) ((maxValue - minValue) / (YValueNum - 1));
        for (int i = 0; i < YValueNum; i++) {
            double value = disY * i + minValue;
            canvas.drawText(df.format(value), viewPadding, (float) ((maxValue - value) / (maxValue - minValue) * chartHeight + viewPadding + textHigh + getTextBottom(textPaint)), textPaint);
        }
    }

    private void drawX(Canvas canvas) {
        if (stampInfoList == null || stampInfoList.size() == 0)
            return;
        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.RIGHT);
        for (int i = 0; i <= XValueNum; i++) {
            int time = startTime + i * XDay * 24 * 60 * 60;
            canvas.drawText(StringUtil.formatDate(time, "MMdd"),
                    left + chartWidth / (XValueNum - 1) * i, viewHeight - viewPadding, textPaint);
        }
        int len5 = (int) textPaint.measureText("MA5:88888.88");
        textPaint.setColor(MA5Color);
        textPaint.setTextAlign(Paint.Align.LEFT);
        if (MA5 == -1)
            canvas.drawText("MA5:--", left, viewPadding - getTextTop(textPaint), textPaint);
        else
            canvas.drawText("MA5:" + df.format(MA5), left, viewPadding - getTextTop(textPaint), textPaint);
        int len10 = (int) textPaint.measureText("MA10:88888.88");
        textPaint.setColor(MA10Color);
        if (MA10 == -1)
            canvas.drawText("MA10:--", left + len5, viewPadding - getTextTop(textPaint), textPaint);
        else
            canvas.drawText("MA10:" + df.format(MA10), left + len5, viewPadding - getTextTop(textPaint), textPaint);
        textPaint.setColor(Ma20Color);
        if (MA20 == -1)
            canvas.drawText("MA20:--", left + len5 + len10, viewPadding - getTextTop(textPaint), textPaint);
        else
            canvas.drawText("MA20:" + df.format(MA20), left + len5 + len10, viewPadding - getTextTop(textPaint), textPaint);
    }

    private void drawBorder(Canvas canvas) {
        linePaint.setStrokeWidth(1);
        linePaint.setColor(bordColor);
        canvas.drawLine(left, top, right, top, linePaint);
        canvas.drawLine(left, bottom, right, bottom, linePaint);
        canvas.drawLine(left, top, left, bottom, linePaint);
        canvas.drawLine(right, top, right, bottom, linePaint);
        linePaint.setColor(charDivideLineColor);
        double disY = (maxValue - minValue) / (YValueNum - 1);
        for (int i = 1; i <= YValueNum - 1; i++) {
            double value = disY * i + minValue;
            int y = (int) (viewPadding + textHigh + (maxValue - value) / (maxValue - minValue) * chartHeight);
            canvas.drawLine(left, y, right, y, linePaint);
        }
        double disX = chartWidth * 1.0 / (XValueNum - 1);
        for (int i = 1; i < XValueNum - 1; i++) {
            int x = (int) (i * disX + left);
            canvas.drawLine(x, top, x, bottom, linePaint);
        }
    }

    private void drawCandleSticks(Canvas canvas) {
        if (stampInfoList == null || stampInfoList.size() == 0)
            return;
        int disX = getTimeX(stampInfoList.get(0).update_time + 24 * 60 * 60) - getTimeX(stampInfoList.get(0).update_time);
        if (disX < defaultStickWidth) {
            stickWidth = disX;
        } else {
            stickWidth = defaultStickWidth;
        }
        for (int i = 0; i < stampInfoList.size(); i++) {
            int high, low, open, close;
            int centerX;
            UserModels.StampInfo info = stampInfoList.get(i);
            high = getPriceY(info.HighPrice);
            low = getPriceY(info.LowPrice);
            open = getPriceY(info.OpenPrice);
            close = getPriceY(info.YesterBalancePrice);
            centerX = getTimeX(info.update_time);
            Rect rect = new Rect();
            disX = 20;
            if (info.OpenPrice < info.YesterBalancePrice) {
                linePaint.setColor(upTextColor);
                rect.set(centerX - disX / 2, close, centerX + disX / 2, open);
                canvas.drawRect(rect, linePaint);
            } else {
                linePaint.setColor(downTextColor);
                rect.set(centerX - disX / 2, open, centerX + disX / 2, close);
                canvas.drawRect(rect, linePaint);
            }
            linePaint.setStrokeWidth(1);
            canvas.drawLine(centerX, high, centerX, low, linePaint);
        }


    }

    private void drawMA(Canvas canvas) {

        if (stampInfoList == null || stampInfoList.size() == 0)
            return;
        if (stampInfoList.size() < 5)
            return;
        //MA5
        MA5 = 0;
        linePaint.setColor(MA5Color);
        linePaint.setStrokeWidth(2);
        linePaint.setTextAlign(Paint.Align.LEFT);
        double ave = 0;
        for (int i = 0; i < 5; i++) {
            UserModels.StampInfo info = stampInfoList.get(i);
            ave += info.YesterBalancePrice;
        }
        ave /= 5;
        int oldx, oldy;
        oldy = getPriceY((float) ave);
        oldx = getTimeX(stampInfoList.get(4).update_time);

        for (int i = 5; i < stampInfoList.size(); i++) {
            ave = 0;
            for (int j = 0; j < 5; j++) {
                UserModels.StampInfo info = stampInfoList.get(i - j);
                ave += info.YesterBalancePrice;
            }
            ave /= 5;
            MA5 += ave;
            int y = getPriceY((float) ave);
            int x = getTimeX(stampInfoList.get(i).update_time);
            canvas.drawLine(oldx, oldy, x, y, linePaint);
            oldx = x;
            oldy = y;
        }
        MA5 /= stampInfoList.size() - 4;
        //MA10
        if (stampInfoList.size() < 10)
            return;
        MA10 = 0;
        linePaint.setColor(MA10Color);
        ave = 0;
        for (int i = 0; i < 10; i++) {
            UserModels.StampInfo info = stampInfoList.get(i);
            ave += info.YesterBalancePrice;
        }
        ave /= 10;
        oldy = getPriceY((float) ave);
        oldx = getTimeX(stampInfoList.get(9).update_time);

        for (int i = 10; i < stampInfoList.size(); i++) {
            ave = 0;
            for (int j = 0; j < 10; j++) {
                UserModels.StampInfo info = stampInfoList.get(i - j);
                ave += info.YesterBalancePrice;
            }
            ave /= 10;
            MA10 += ave;
            int y = getPriceY((float) ave);
            int x = getTimeX(stampInfoList.get(i).update_time);
            canvas.drawLine(oldx, oldy, x, y, linePaint);
            oldx = x;
            oldy = y;
        }
        MA10 /= stampInfoList.size() - 9;
        //MA20
        if (stampInfoList.size() < 20)
            return;
        MA20 = 0;
        linePaint.setColor(MA10Color);
        ave = 0;
        for (int i = 0; i < 20; i++) {
            UserModels.StampInfo info = stampInfoList.get(i);
            ave += info.YesterBalancePrice;
        }
        ave /= 20;
        oldy = getPriceY((float) ave);
        oldx = getTimeX(stampInfoList.get(19).update_time);

        for (int i = 20; i < stampInfoList.size(); i++) {
            ave = 0;
            for (int j = 0; j < 20; j++) {
                UserModels.StampInfo info = stampInfoList.get(i - j);
                ave += info.YesterBalancePrice;
            }
            ave /= 20;
            MA20 += ave;
            int y = getPriceY((float) ave);
            int x = getTimeX(stampInfoList.get(i).update_time);
            canvas.drawLine(oldx, oldy, x, y, linePaint);
            oldx = x;
            oldy = y;
        }
        MA20 /= stampInfoList.size() - 19;

    }


    private void drawHint(Canvas canvas) {
        if (currentX == -1 || currentY == -1 || stampInfoList == null || stampInfoList.size() == 0)
            return;
        if (!(currentX <= right && currentX >= left && currentY >= top && currentY <= bottom))
            return;
        linePaint.setStrokeWidth(1);
        linePaint.setColor(hintLineColor);
        textPaint.setColor(defaultTextColor);
        textPaint.setTextAlign(Paint.Align.CENTER);
        int position = getDataNum();
        if (position != -1) {
            UserModels.StampInfo info = stampInfoList.get(position);
            canvas.drawLine(getTimeX(info.update_time), top, getTimeX(info.update_time), bottom, linePaint);
            drawHintDetail(canvas, position);
        }
    }

    private void drawHintDetail(Canvas canvas, int position) {
        // 绘制点击线条及详情区域
        UserModels.StampInfo info = stampInfoList.get(position);
        linePaint.setColor(Color.BLACK);
        linePaint.setAlpha(150);
        int borderLeft, borderRight, borderTop, borderBottom;


        if (getTimeX(info.update_time) > left + chartWidth * 1.0 / 2) {
            borderLeft = left;
            borderRight = left + hintBorderWidth + 2 * hintBorderPadding;
            borderTop = top;
            borderBottom = top + textHigh * 5 + 2 * hintBorderPadding;
        } else {
            borderLeft = right - (hintBorderWidth + 2 * hintBorderPadding);
            borderRight = right;
            borderTop = top;
            borderBottom = top + textHigh * 5 + 2 * hintBorderPadding;
        }
        canvas.drawRect(borderLeft, borderTop, borderRight, borderBottom, linePaint);
        textPaint.setTextAlign(Paint.Align.LEFT);
        try {
            canvas.drawText("日期: " + StringUtil.formatDate(info.update_time, "yyyyMMdd"), borderLeft + hintBorderPadding, borderTop + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("开盘: ", borderLeft + hintBorderPadding, borderTop + textHigh * 1.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("收盘: ", borderLeft + hintBorderPadding, borderTop + textHigh * 2.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("最高: ", borderLeft + hintBorderPadding, borderTop + textHigh * 3.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("最低: ", borderLeft + hintBorderPadding, borderTop + textHigh * 4.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            if (info.OpenPrice < info.YesterBalancePrice) {
                textPaint.setColor(upTextColor);
            } else {
                textPaint.setColor(downTextColor);
            }
            canvas.drawText(df.format(info.OpenPrice), borderLeft + hintBorderPadding + hintBorderLeftTextWidth, borderTop + textHigh * 1.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText(df.format(info.YesterBalancePrice), borderLeft + hintBorderPadding + hintBorderLeftTextWidth, borderTop + textHigh * 2.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText(df.format(info.HighPrice), borderLeft + hintBorderPadding + hintBorderLeftTextWidth, borderTop + textHigh * 3.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText(df.format(info.LowPrice), borderLeft + hintBorderPadding + hintBorderLeftTextWidth, borderTop + textHigh * 4.0f + hintBorderPadding - getTextTop(textPaint), textPaint);

        } catch (Exception e) {
            canvas.drawText("日期: -- --", borderLeft + hintBorderPadding, borderTop + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("开盘: -- --", borderLeft + hintBorderPadding, borderTop + textHigh * 1.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("收盘: -- --", borderLeft + hintBorderPadding, borderTop + textHigh * 2.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("最高: -- --", borderLeft + hintBorderPadding, borderTop + textHigh * 3.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
            canvas.drawText("最低: -- --", borderLeft + hintBorderPadding, borderTop + textHigh * 4.0f + hintBorderPadding - getTextTop(textPaint), textPaint);
        }

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(widthMeasureSpec, viewHeight);
        chartWidth = getWidth() - 2 * viewPadding - leftTextLenght;
        top = textHigh + viewPadding;
        left = viewPadding + leftTextLenght;
        right = getWidth() - viewPadding;
        bottom = textHigh + viewPadding + chartHeight;
    }


    private boolean judgeDownOrUp(float x, float y) {
        if (Math.abs(currentX - x) + 10 < Math.abs(currentY - y)) {
            return true;
        } else {
            return false;
        }
    }

    private int getTextBottom(Paint textPaint) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return (int) fontMetrics.bottom;
    }

    private int getTextTop(Paint textPaint) {
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        return (int) fontMetrics.top;
    }

    private int getPriceY(float curPrice) {
        return (int) ((maxValue - curPrice) * 1.0 / (maxValue - minValue) * chartHeight + viewPadding + textHigh);
    }


    private int getTimeX(int update_time) {
        return (int) ((update_time - startTime) * 1.0 / (endTime - startTime) * chartWidth + leftTextLenght + viewPadding);
    }

    public void setTouchListener(TouchListener touchListener) {
        this.touchListener = touchListener;
    }

    public int sp2px(float spValue) {
        final float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    private int getDataNum() {
        for (int i = 0; i < stampInfoList.size(); i++) {
            UserModels.StampInfo info = stampInfoList.get(i);
            if (Math.abs(getTimeX(info.update_time) - currentX) < stickWidth) {
                return i;
            }
        }
        return -1;
    }

    private int getTextHight(Paint paint) {
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        return (int) (fontMetrics.bottom - fontMetrics.top + 0.5f);
    }

    public void setStampInfoList(List stampInfoList) {
        this.stampInfoList = stampInfoList;
        if (stampInfoList == null || stampInfoList.size() == 0)
            return;
        maxValue = Float.MIN_VALUE;
        minValue = Float.MAX_VALUE;
        for (int i = 0; i < stampInfoList.size(); i++) {
            UserModels.StampInfo info = stampInfoList.get(i);
            maxValue = maxValue > info.HighPrice ? maxValue : info.HighPrice;
            minValue = minValue < info.LowPrice ? minValue : info.LowPrice;

            minValue = minValue < info.YesterBalancePrice ? minValue : info.YesterBalancePrice;
            minValue = minValue < info.OpenPrice ? minValue : info.OpenPrice;
            maxValue = maxValue > info.OpenPrice ? maxValue : info.OpenPrice;
            maxValue = maxValue > info.YesterBalancePrice ? maxValue : info.YesterBalancePrice;
        }
        startTime = stampInfoList.get(0).update_time;
        startTime -= 24 * 60 * 60;
        endTime = stampInfoList.get(stampInfoList.size() - 1).update_time;
        if (startTime - endTime < 40 * 24 * 60 * 60) {
            XValueNum = 5;
            XDay = 10;
        } else {
            XValueNum = (startTime - endTime) / (10 * 24 * 60 * 60) + 2;
            XDay = 10;
        }
        endTime = startTime + (XValueNum - 1) * XDay * 24 * 60 * 60;
        this.postInvalidate();
    }
}


你可能感兴趣的:(android)