Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 開發:帶觸控的圖表(基金圖表的實現)

Android 開發:帶觸控的圖表(基金圖表的實現)

編輯:關於Android編程

帶觸控的圖表類,後期會把這個功能類,添加到這個框架裡:
效果如下
圖片描述
圖片描述

public class BaseFundChartView extends View implements View.OnTouchListener{

    Paint linePaint;
    Paint textPaint;
    Paint xyChartPaint;
    Paint chartLinePaint;
    Paint chartJianbianPaint;
    Paint huodongPaint;
    Paint huodongPaintText;
    List points;
    public BaseFundChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public BaseFundChartView(Context context) {
        this(context, null);
    }

    public BaseFundChartView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    PathEffect effect;
    Path path;

    private float getWidthYMax(){
        return getWidth()-15;
    }

    private void init() {
        linePaint = new Paint();
        textPaint = new Paint();
        xyChartPaint = new Paint();
        chartLinePaint = new Paint();
        chartJianbianPaint = new Paint();
        huodongPaint = new Paint();
        huodongPaintText = new Paint();
        //設置繪制模式為-虛線作為背景線。
        effect = new DashPathEffect(new float[] { 6, 6, 6, 6, 6}, 2);
        //背景虛線路徑.
        path = new Path();
        //只是繪制的XY軸
        linePaint.setStyle(Paint.Style.STROKE);
//        linePaint.setStrokeWidth((float) 0.7);
        linePaint.setStrokeWidth((float) 1.0);             //設置線寬

        linePaint.setColor(Color.BLACK);
        linePaint.setAntiAlias(true);// 鋸齒不顯示

        //XY刻度上的字
        textPaint.setStyle(Paint.Style.FILL);// 設置非填充
        textPaint.setStrokeWidth(1);// 筆寬5像素
        textPaint.setColor(Color.BLACK);// 設置為藍筆
        textPaint.setAntiAlias(true);// 鋸齒不顯示
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setTextSize(15);

        //繪制XY軸上的字:Y開關狀態、X時間
        xyChartPaint.setStyle(Paint.Style.FILL);
        xyChartPaint.setStrokeWidth(1);
        xyChartPaint.setColor(Color.BLUE);
        xyChartPaint.setAntiAlias(true);
        xyChartPaint.setTextAlign(Paint.Align.CENTER);
        xyChartPaint.setTextSize(18);
        //繪制的折線
        chartLinePaint.setStyle(Paint.Style.STROKE);
        chartLinePaint.setStrokeWidth(5);
        chartLinePaint.setColor(Color.BLUE);
        chartLinePaint.setAntiAlias(true);

        //繪制的折線
        chartJianbianPaint.setStyle(Paint.Style.FILL);
        chartJianbianPaint.setStrokeWidth(5);
        //chartJianbianPaint.setColor(Color.YELLOW);

        chartJianbianPaint.setAntiAlias(true);


        huodongPaint.setStyle(Paint.Style.STROKE);
        huodongPaint.setStrokeWidth((float) 3.0);             //設置線寬

        huodongPaint.setColor(Color.GRAY);
        huodongPaint.setAntiAlias(true);// 鋸齒不顯示

        huodongPaintText.setStyle(Paint.Style.STROKE);
        huodongPaintText.setStrokeWidth((float) 2.0);             //設置線寬
        huodongPaintText.setTextSize(40);
        huodongPaintText.setColor(Color.GRAY);
        huodongPaintText.setAntiAlias(true);// 鋸齒不顯示

        setOnTouchListener(this);
    }

    /**
     * 重要參數,兩點之間分為幾段描畫,數字愈大分段越多,描畫的曲線就越精細.
     */
    private static final int STEPS = 12;

    float gridX,gridY,xSpace = 0,ySpace = 0,spaceYT = 0;
    Float yStart=null,yStop = null;
    Integer yCount = null;

    List text = null;

    public void setText(List text) {
        this.text = text;
    }

    public void setyCount(Integer yCount) {
        this.yCount = yCount;
    }

    public void setyStart(Float yStart) {
        this.yStart = yStart;
    }

    public void setyStop(Float yStop) {
        this.yStop = yStop;
    }

    String yFormat=null;

    public void setFormat(String yFormat){
        this.yFormat = yFormat;
    }

    List dateX = null;
    List dateY = null;

    List> data = null;

    List colors = null;

    public void setColors(List colors) {
        this.colors = colors;
    }

    public List getDateY() {
        return dateY;
    }

    public void setDateY(List dateY) {
        this.dateY = dateY;
    }

    public List> getData() {
        return data;
    }

    public void setData(List> data) {
        this.data = data;
    }

    public List getDateX() {
        return dateX;
    }

    public void setDateX(List dateX) {
        this.dateX = dateX;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //基准點。
        gridX = 40;
        gridY = getHeight() - 50;
        //XY間隔。
        if(dateX!=null&&dateX.size()>0){
            xSpace = (getWidthYMax() - gridX)/dateX.size();
        }
        /**
         * 如果設置開頭和結尾的話,就直接生成y軸
         */
        if(yStart!=null&&yStop!=null&&yCount!=null){
            dateY = new ArrayList<>();
            ySpace = (gridY - 70)/yCount;
            float ze = (yStop-yStart)/yCount;
            for(int i=0;i2){
                spaceYT = dateY.get(1)-dateY.get(0);
            }
        }else{
            if(dateY!=null&&dateY.size()>0){
                ySpace = (gridY - 70)/dateY.size();
                yStart = dateY.get(0);
                if(dateY.size()>2){
                    spaceYT = dateY.get(1)-dateY.get(0);
                }
            }
        }



        UIUtils.log("rewqfdesa",gridY,"fdsafdsa");

        //畫Y軸(帶箭頭)。
        canvas.drawLine(gridX, gridY - 20 - 10, gridX,  10, linePaint);
        canvas.drawLine(gridX,  10, gridX - 6, 14 + 10, linePaint);//Y軸箭頭。
        canvas.drawLine(gridX,  10, gridX + 6, 14 + 10, linePaint);



        //畫Y軸名字。
        //由於是豎直顯示的,先以原點順時針旋轉90度後為新的坐標系
        //canvas.rotate(-90);
        //當xyChartPaint的setTextAlign()設置為center時第二、三個參數代表這四個字中點所在的xy坐標

        //canvas.drawText("開關狀態", -((float) (getHeight() - 60) - 15 - 5 - 1 / ((float) 1.6 * 1) * (getHeight() - 60) / 2), gridX - 15, xyChartPaint);
        //繪制Y軸坐標


        //canvas.rotate(90); //改變了坐標系還要再改過來
        float y = 0;
        //畫X軸。
        y = gridY - 20;
        canvas.drawLine(gridX, y - 10, getWidthYMax(), y - 10, linePaint);//X軸.
        canvas.drawLine(getWidthYMax(), y - 10, getWidthYMax() - 14, y - 6 - 10, linePaint);//X軸箭頭。
        canvas.drawLine(getWidthYMax(), y - 10, getWidthYMax() - 14, y + 6 - 10, linePaint);

        //繪制X刻度坐標。
        float x = 0;
        if(dateX!=null){
            for (int n = 0; n < dateX.size(); n++) {
                //取X刻度坐標.
                x = gridX + (n) * xSpace;//在原點(0,0)處也畫刻度(不畫的話就是n+1),向右移動一個跨度。
                //畫X軸具體刻度值。
                if (dateX.get(n) != null) {
                    //canvas.drawLine(x, gridY - 30, x, gridY - 18, linePaint);//短X刻度。
                    canvas.drawText(dateX.get(n), x, gridY + 5, textPaint);//X具體刻度值。
                }
            }
        }

        float my = 0;

        if(dateY!=null){

            for(int n=0;n0){
            float lastPointX = 0; //前一個點
            float lastPointY = 0;
            float currentPointX = 0;//當前點
            float currentPointY = 0;
            for(int n=0;n da = data.get(n);
                List da_x = new ArrayList<>();
                List da_y = new ArrayList<>();
                /**
                 * 曲線路勁
                 */
                Path curvePath = new Path();
                /**
                 * 漸變色路徑
                 */
                Path jianBianPath = new Path();

                for(int m=0;m0){
//                        canvas.drawLine(lastPointX, lastPointY, currentPointX, currentPointY, chartLinePaint);
//                    }
//                    lastPointX = currentPointX;
//                    lastPointY = currentPointY;
                }
                List calculate_y = calculate(da_y);
                List calculate_x = calculate(da_x);
                curvePath.moveTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
                jianBianPath.moveTo(gridX,gridY - 20 - 10);
                jianBianPath.lineTo(calculate_x.get(0).eval(0), calculate_y.get(0).eval(0));
                chartLinePaint.setColor(colors.get(n));
                float lastx = 0;
                for (int i = 0; i < calculate_x.size(); i++) {
                    for (int j = 1; j <= STEPS; j++) {
                        float u = j / (float) STEPS;
                        curvePath.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i)
                                .eval(u));
                        jianBianPath.lineTo(calculate_x.get(i).eval(u), calculate_y.get(i)
                                .eval(u));
                        lastx = calculate_x.get(i).eval(u);
                    }
                }
                jianBianPath.lineTo(lastx,gridY - 20 - 10);
                canvas.drawPath(curvePath, chartLinePaint);
                Shader mShader = new LinearGradient(0,30 + 10,0,gridY - 20 - 10,new int[] {colors.get(n),Color.TRANSPARENT},null,Shader.TileMode.REPEAT);
//新建一個線性漸變,前兩個參數是漸變開始的點坐標,第三四個參數是漸變結束的點的坐標。連接這2個點就拉出一條漸變線了,玩過PS的都懂。然後那個數組是漸變的顏色。下一個參數是漸變顏色的分布,如果為空,每個顏色就是均勻分布的。最後是模式,這裡設置的是循環漸變

                chartJianbianPaint.setShader(mShader);
                canvas.drawPath(jianBianPath, chartJianbianPaint);
            }
        }

        if(lineX!=null){
            if(text!=null&&text.size()>0){
                Paint.FontMetrics metrics = huodongPaintText.getFontMetrics();
                float top = metrics.top;
                float bootom = metrics.bottom;
                float h = bootom-top;
                float th = h + h*text.size();
                float w=0;
                float fx = 1;
                if(lineX>getWidth()/2){
                    fx = -1;
                }else{
                    fx = 1;
                }
                for(int i=0;iw){
                        w = width;
                    }
                    canvas.drawText(text.get(i),fx==1?lineX+10:lineX-10-width,40+ h*(i+1),huodongPaintText);
                }
                canvas.drawLine(lineX, gridY - 20 - 10, lineX, 30 + 10, huodongPaint);
                //canvas.drawRect(lineX,40,lineX+w*fx+20*fx,40+th,huodongPaint);
            }
        }





//        //起始點。
//        float lastPointX = 0; //前一個點
//        float lastPointY = 0;
//        float currentPointX = 0;//當前點
//        float currentPointY = 0;
//        if (dateY != null) {
//            //1.繪制折線。
//            for (int n = 0; n < dateY.length; n++) {
//                //get current point
//                currentPointX = n * xSpace + gridX;
//                currentPointY = (float) (getHeight() - 60) - 15 - 5 - (float) dateY[n] / ((float) 1.6 * 1) * (getHeight() - 60);
//                if (dateX[n] != null) {//用X來判斷,就是用來如果剛開始的點數少於7個則從左到右遞增,從而沒有了剛開始的幾個虛點;(因為X和Y的數組初始化時都沒賦值,所以剛開始的時候用這個就可以判斷數組中到底幾個點)
//                    if (n > 0) {//從第二個點開始判斷
//                        if (dateY[n - 1] == dateY[n]) {//如果相鄰兩個點相等一直畫直線
//                            //draw line
//                            canvas.drawLine(lastPointX, lastPointY, currentPointX, currentPointY, chartLinePaint);//第一條線[藍色]
//                        } else {//如果相鄰間的點不相等證明是從開到關或者關到開的狀態,要畫豎線
//                            //draw line  橫線
//                            canvas.drawLine(lastPointX, lastPointY, currentPointX, lastPointY, chartLinePaint);//第一條線[藍色]
//                            //draw line  豎線
//                            canvas.drawLine(currentPointX, lastPointY, currentPointX, currentPointY, chartLinePaint);//第一條線[藍色]
//                        }
//                    }
//                }
//
//                lastPointX = currentPointX;
//                lastPointY = currentPointY;
//            }
//        }




        //畫背景虛線,一條(因為除去了X軸),畫Y軸刻度
 //       y = (float) (getHeight() - 60) - 15 - 5 - 1 / ((float) 1.6 * 1) * (getHeight() - 60);//虛線的Y,開關是開的時候的Y。
//        linePaint.setPathEffect(effect);//設法虛線間隔樣式。
//        //畫除X軸之外的------背景虛線一條-------
//        path.moveTo(gridX, y);//背景【虛線起點】。
//        path.lineTo(getWidth(), y);//背景【虛線終點】。
//        canvas.drawPath(path, linePaint);
//        //畫Y軸刻度。
//        canvas.drawText("關", gridX - 6 - 7, gridY - 20, textPaint);
//        canvas.drawText("開", gridX - 6 - 7, y + 10, textPaint);
//
//        //繪制X刻度坐標。
//        float x = 0;
//        if (dateX[0] != null) { //用X來判斷,就是用來如果剛開始的點數少於7個則從左到右遞增,從而沒有了剛開始的幾個虛點;(因為X和Y的數組初始化時都沒賦值,所以剛開始的時候用這個就可以判斷數組中到底幾個點)
//            for (int n = 0; n < dateX.length; n++) {
//                //取X刻度坐標.
//                x = gridX + (n) * xSpace;//在原點(0,0)處也畫刻度(不畫的話就是n+1),向右移動一個跨度。
//                //畫X軸具體刻度值。
//                if (dateX[n] != null) {
//                    canvas.drawLine(x, gridY - 30, x, gridY - 18, linePaint);//短X刻度。
//                    canvas.drawText(dateX[n], x, gridY + 5, textPaint);//X具體刻度值。
//                }
//            }
//        }
//
//        //起始點。
//        float lastPointX = 0; //前一個點
//        float lastPointY = 0;
//        float currentPointX = 0;//當前點
//        float currentPointY = 0;
//        if (dateY != null) {
//            //1.繪制折線。
//            for (int n = 0; n < dateY.length; n++) {
//                //get current point
//                currentPointX = n * xSpace + gridX;
//                currentPointY = (float) (getHeight() - 60) - 15 - 5 - (float) dateY[n] / ((float) 1.6 * 1) * (getHeight() - 60);
//                if (dateX[n] != null) {//用X來判斷,就是用來如果剛開始的點數少於7個則從左到右遞增,從而沒有了剛開始的幾個虛點;(因為X和Y的數組初始化時都沒賦值,所以剛開始的時候用這個就可以判斷數組中到底幾個點)
//                    if (n > 0) {//從第二個點開始判斷
//                        if (dateY[n - 1] == dateY[n]) {//如果相鄰兩個點相等一直畫直線
//                            //draw line
//                            canvas.drawLine(lastPointX, lastPointY, currentPointX, currentPointY, chartLinePaint);//第一條線[藍色]
//                        } else {//如果相鄰間的點不相等證明是從開到關或者關到開的狀態,要畫豎線
//                            //draw line  橫線
//                            canvas.drawLine(lastPointX, lastPointY, currentPointX, lastPointY, chartLinePaint);//第一條線[藍色]
//                            //draw line  豎線
//                            canvas.drawLine(currentPointX, lastPointY, currentPointX, currentPointY, chartLinePaint);//第一條線[藍色]
//                        }
//                    }
//                }
//
//                lastPointX = currentPointX;
//                lastPointY = currentPointY;
//            }
//        }
//        //畫X軸名字。
//        canvas.drawText("時間", getWidth() / 2 - 10, getHeight() - 18, xyChartPaint);
    }

//    /**
//     * 畫點.
//     *
//     * @param canvas
//     */
//    private void drawPoints(Canvas canvas) {
//        for (int i = 0; i < points.size(); i++) {
//            Point p = points.get(i);
//            canvas.drawCircle(p.x, p.y, 5, paint);
//        }
//    }


    /**
     * 計算曲線.
     *
     * @param x
     * @return
     */
    private List calculate(List x) {
        int n = x.size() - 1;
        float[] gamma = new float[n + 1];
        float[] delta = new float[n + 1];
        float[] D = new float[n + 1];
        int i;
        /*
         * We solve the equation [2 1 ] [D[0]] [3(x[1] - x[0]) ] |1 4 1 | |D[1]|
         * |3(x[2] - x[0]) | | 1 4 1 | | . | = | . | | ..... | | . | | . | | 1 4
         * 1| | . | |3(x[n] - x[n-2])| [ 1 2] [D[n]] [3(x[n] - x[n-1])]
         *
         * by using row operations to convert the matrix to upper triangular and
         * then back sustitution. The D[i] are the derivatives at the knots.
         */

        gamma[0] = 1.0f / 2.0f;
        for (i = 1; i < n; i++) {
            gamma[i] = 1 / (4 - gamma[i - 1]);
        }
        gamma[n] = 1 / (2 - gamma[n - 1]);

        delta[0] = 3 * (x.get(1) - x.get(0)) * gamma[0];
        for (i = 1; i < n; i++) {
            delta[i] = (3 * (x.get(i + 1) - x.get(i - 1)) - delta[i - 1])
                    * gamma[i];
        }
        delta[n] = (3 * (x.get(n) - x.get(n - 1)) - delta[n - 1]) * gamma[n];

        D[n] = delta[n];
        for (i = n - 1; i >= 0; i--) {
            D[i] = delta[i] - gamma[i] * D[i + 1];
        }

        /* now compute the coefficients of the cubics */
        List cubics = new LinkedList();
        for (i = 0; i < n; i++) {
            Cubic c = new Cubic(x.get(i), D[i], 3 * (x.get(i + 1) - x.get(i))
                    - 2 * D[i] - D[i + 1], 2 * (x.get(i) - x.get(i + 1)) + D[i]
                    + D[i + 1]);
            cubics.add(c);
        }
        return cubics;
    }


    Float lineX = null;

    Integer temp = null;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        getParent().requestDisallowInterceptTouchEvent(true);
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                float zhi = (event.getX()-gridX)%xSpace;
                boolean fanwei = zhi>0&&zhi0&&fanwei&&event.getX()
        
   
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved