自己定义的View曲线图 多点触控 canvas

源码 可能不太优雅 但是主要是提供给出大家一点 思路 相信 Android 只有想不到 没有做不到的。

先看一下效果图:

自己定义的View曲线图 多点触控 canvas

静止

自己定义的View曲线图 多点触控 canvas

单点触控

自己定义的View曲线图 多点触控 canvas

多点触控

部分代码:

EnergyItem.java

package com.example.energycurve.ben;



/**

 * 能耗 Bean

 * @author keven.cheng

 *

 */

public class EnergyItem {



    public String date;    //时间值

    public float value;    //能量

    public String time;    //使用时间

    

    public EnergyItem() {

        super();

    }

    public EnergyItem(String date, float value, String time) {

        super();

        this.date = date;

        this.value = value;

        this.time = time;

    }

    

    

}

 

/**

     * 初始化绘制

     * 

     * @param canvas

     * @param paint

     */

    private void initDraw(Canvas canvas, Paint paint) {

        paint.setColor(Color.WHITE);

        paint.setAntiAlias(true);

        paint.setStrokeWidth(3);

        /* 裁剪出一个需要的矩阵图 */

        Path path = new Path();

        PointF point = null;

        path.moveTo(SPACING, mGradientHeight + SPACING_HEIGHT);

        for (int i = 0; i < points.size(); i++) {

            point = points.get(i);

            path.lineTo(point.x, point.y - SPACING_HEIGHT);

        }

        path.lineTo(point.x, mGradientHeight + SPACING_HEIGHT);

        path.lineTo(SPACING, mGradientHeight + SPACING_HEIGHT);

        path.close();

        Bitmap btm = Bitmap.createBitmap((int) mGradientWidth,

                (int) mGradientHeight, Config.ARGB_8888);

        Bitmap creatBitmap = creatBitmap(paint, path, btm);

        /* 绘制底部的横线、文字、以及向上的线条 */

        canvas.drawLine(SPACING, mGradientHeight + SPACING_HEIGHT,

                mGradientWidth, mGradientHeight + SPACING_HEIGHT, paint);

        for (int i = 0; i < energyItems.size(); i++) {

            EnergyItem energy = energyItems.get(i);

            PointF textPoint = points.get(i);

            paint.setColor(Color.GRAY);

            paint.setStrokeWidth(1);

            // 绘制底部 到上面的线

            canvas.drawLine(textPoint.x, mGradientHeight + SPACING_HEIGHT,

                    textPoint.x, SPACING_HEIGHT + WEIGHT + 3, paint);

            paint.setColor(Color.WHITE);

            // 绘制底部的 文字

            canvas.drawText(energy.date, textPoint.x - 15, mGradientHeight

                    + SPACING_HEIGHT + 20, paint);

        }

        /* 绘制虚线 */

        Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        PathEffect effects = new DashPathEffect(new float[] { 3, 3, 3, 3 }, 3);

        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setAntiAlias(true);

        mPaint.setStrokeWidth(1);

        mPaint.setPathEffect(effects);

        float dottedSpacing = (mGradientHeight - WEIGHT) / 4;

        float smallDotted = dottedSpacing / 10;

        for (int i = 1; i <= 4; i++) {

            Path dottedPath = new Path();

            mPaint.setColor(Color.GRAY);

            mPaint.setAlpha(0x50);

            dottedPath.moveTo(SPACING, mGradientHeight + SPACING_HEIGHT

                    - dottedSpacing * i);

            dottedPath.lineTo(mGradientWidth, mGradientHeight + SPACING_HEIGHT

                    - dottedSpacing * i);

            canvas.drawPath(dottedPath, mPaint);

        }

        /* 左边刻度尺 */

        float digit = ((maxEnergy.value) / 4 + maxEnergy.value) / 4;

        for (int i = 1; i <= 4; i++) {

            paint.setStrokeWidth(1);

            int digitInt = (int) (digit * i + 1.0e-6);

            canvas.drawText(String.valueOf(digitInt), SPACING - 25,

                    mGradientHeight + SPACING_HEIGHT - dottedSpacing * i + 5,

                    paint);

            canvas.drawLine(SPACING, mGradientHeight + SPACING_HEIGHT

                    - dottedSpacing * i, SPACING + 10, mGradientHeight

                    + SPACING_HEIGHT - dottedSpacing * i, paint);

            for (int j = 0; j <= 10; j++) {

                if (j == 5) {

                    canvas.drawLine(SPACING, mGradientHeight + SPACING_HEIGHT

                            - dottedSpacing * i + smallDotted * j,

                            SPACING + 10, mGradientHeight + SPACING_HEIGHT

                                    - dottedSpacing * i + smallDotted * j,

                            paint);

                } else {

                    canvas.drawLine(SPACING, mGradientHeight + SPACING_HEIGHT

                            - dottedSpacing * i + smallDotted * j, SPACING + 5,

                            mGradientHeight + SPACING_HEIGHT - dottedSpacing

                                    * i + smallDotted * j, paint);

                }

            }

        }

        // 绘制裁剪后的矩阵图

        canvas.drawBitmap(creatBitmap, 0, SPACING_HEIGHT, paint);



        /* 绘制曲线 覆盖 剪切后的锯齿 */

        for (int i = 0; i < points.size(); i++) {

            paint.setStrokeWidth(3);

            PointF startPoint = points.get(i);

            if (i + 1 == points.size()) {

                // 绘制最后一个圆点到底部的 竖线

                paint.setStrokeWidth(1);

                canvas.drawLine(startPoint.x, startPoint.y, startPoint.x,

                        mGradientHeight + SPACING_HEIGHT, paint);

                // 绘制 最后一个圆点 为剪切的图片

                canvas.drawBitmap(mLastPoint,

                        startPoint.x - mLastPoint.getWidth() / 2, startPoint.y

                                - mLastPoint.getHeight() / 2, paint);

                break;

            }

            PointF endPoint = points.get(i + 1);

            // 绘制曲线,并且覆盖剪切后的锯齿

            canvas.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y,

                    paint);

            // 为了使线条圆滑 绘一个点 每个坐标系 绘制一个圆点

            canvas.drawPoint(startPoint.x, startPoint.y, paint);

        }
// 绘制左边的竖线,以及温度的刻度 (由于需要与顶边 产生间距SPACING_HEIGHT)———— 目前模拟 待修改
  canvas.drawLine(SPACING, SPACING_HEIGHT, SPACING, mGradientHeight
    + SPACING_HEIGHT, paint);
  // 绘制右边的 字(时、天、月)通过Type来进行修改———— 目前模拟 待修改
  paint.setTextSize(16);
  canvas.drawText("天", mGradientWidth + 5, mGradientHeight
    + SPACING_HEIGHT + 5, paint);
  canvas.drawText("度", SPACING - 8, 30, paint);
 }

单点触摸

/**

     * 单点触控操作

     * 

     * @param canvas

     * @param paint

     */

    private void SinglePointTouch(Canvas canvas, Paint paint) {

        // 顶部的度数框

        if (moveXOfFirst < points.get(0).x) {

            moveXOfFirst = points.get(0).x;

        }

        if (moveXOfFirst > points.get(points.size() - 1).x) {

            moveXOfFirst = points.get(points.size() - 1).x;

        }

        float moveX = moveXOfFirst;

        // 绘制度数框 背景后的 横线

        canvas.drawBitmap(mTitleLine, SPACING, mGradientHeight + SPACING_HEIGHT

                - mTrendLine.getHeight() + 5, paint);

        // 绘制 移动的 点

        onPointMove(canvas, paint, moveXOfFirst, isDown);

        canvas.drawBitmap(

                mDegree,

                moveX - mDegree.getWidth() / 2,

                (mGradientHeight + SPACING_HEIGHT - mTrendLine.getHeight() + 5) / 2,

                paint);



        // 绘制 变动的 能耗为多少



        float moveY = getMoveY(moveXOfFirst);

        float energyHeight = (float) (mGradientHeight + SPACING_HEIGHT) - moveY;



        String energyText = String.valueOf(energyHeight / spacingOfY);

        // 为了避免误差 如果单点 手指在X轴 在预定的 X点上 那么直接将显示读书设置为 服务器传回的数据

        EnergyItem energy = isInPoint(moveXOfFirst);

        if (energy != null) {

            energyText = String.valueOf(energy.value);

        }

        int indexOf = energyText.indexOf(".");

        String substring = energyText.substring(0, indexOf + 2);

        paint.setTextSize(28);

        paint.setColor(Color.BLACK);

        canvas.drawText(substring + "度", moveX - mDegree.getWidth() / 3,

                mGradientHeight + SPACING_HEIGHT - mTrendLine.getHeight()

                        + mDegree.getHeight() / 3, paint);

    }

多点触摸

/**

     * 多点触控操作

     * 

     * @param canvas

     * @param paint

     */

    private void multiPointTouch(Canvas canvas, Paint paint) {

        paint.setColor(Color.rgb(240, 150, 40));

        paint.setStrokeWidth(4);

        // 计算 多点选择 的两个点 分别处在 屏幕的 某个区域内 并且计算出区域中的点

        float pointSpacing = 0.0f; // 两点之间的间距

        if (moveXOfFirst < points.get(0).x) {

            moveXOfFirst = points.get(0).x;

        }

        if (moveXOfFirst > points.get(points.size() - 1).x) {

            moveXOfFirst = points.get(points.size() - 1).x;

        }

        if (moveXOfSecond < points.get(0).x) {

            moveXOfSecond = points.get(0).x;

        }

        if (moveXOfSecond > points.get(points.size() - 1).x) {

            moveXOfSecond = points.get(points.size() - 1).x;

        }

        int moveXOfOne = getLocation(moveXOfFirst);

        int moveXOfTwo = getLocation(moveXOfSecond);

        // 第一个点 小于 第二个点

        if (moveXOfOne < moveXOfTwo) {

            if (!(moveXOfSecond == points.get(points.size() - 1).x)) {

                moveXOfTwo = moveXOfTwo - 1;

            }

            // 重绘 两点间的 的连接线

            canvas.drawLine(moveXOfFirst, getMoveY(moveXOfFirst),

                    points.get(moveXOfOne).x, points.get(moveXOfOne).y, paint);

            for (int j = moveXOfOne; j < moveXOfTwo; j++) {

                PointF startPoint = points.get(j);

                if (j + 1 == points.size()) {

                    // 绘制 最后一个圆点 为剪切的图片

                    canvas.drawBitmap(mLastPoint,

                            startPoint.x - mLastPoint.getWidth() / 2,

                            startPoint.y - mLastPoint.getHeight() / 2, paint);

                    break;

                }

                PointF endPoint = points.get(j + 1);

                // 绘制曲线,并且覆盖剪切后的锯齿

                canvas.drawLine(startPoint.x, startPoint.y, endPoint.x,

                        endPoint.y, paint);

                // 为了使线条圆滑 绘一个点 每个坐标系 绘制一个圆点

                canvas.drawPoint(startPoint.x, startPoint.y, paint);

            }

            canvas.drawLine(points.get(moveXOfTwo).x, points.get(moveXOfTwo).y,

                    moveXOfSecond, getMoveY(moveXOfSecond), paint);

        }

        // 第一个点 大于 第二个点

        if (moveXOfOne > moveXOfTwo) {

            if (!(moveXOfFirst == points.get(points.size() - 1).x)) {

                moveXOfOne = moveXOfOne - 1;

            }

            // 重绘 两点间的 的连接线

            canvas.drawLine(moveXOfSecond, getMoveY(moveXOfSecond),

                    points.get(moveXOfTwo).x, points.get(moveXOfTwo).y, paint);

            for (int j = moveXOfTwo; j < moveXOfOne; j++) {

                PointF startPoint = points.get(j);

                if (j + 1 == points.size()) {

                    // 绘制 最后一个圆点 为剪切的图片

                    canvas.drawBitmap(mLastPoint,

                            startPoint.x - mLastPoint.getWidth() / 2,

                            startPoint.y - mLastPoint.getHeight() / 2, paint);

                    break;

                }

                PointF endPoint = points.get(j + 1);

                // 绘制曲线,并且覆盖剪切后的锯齿

                canvas.drawLine(startPoint.x, startPoint.y, endPoint.x,

                        endPoint.y, paint);

                // 为了使线条圆滑 绘一个点 每个坐标系 绘制一个圆点

                canvas.drawPoint(startPoint.x, startPoint.y, paint);

            }

            canvas.drawLine(points.get(moveXOfOne).x, points.get(moveXOfOne).y,

                    moveXOfFirst, getMoveY(moveXOfFirst), paint);

        }

        // 第一个点 等于 第二个点

        if (getArea(moveXOfFirst) == getArea(moveXOfSecond)) {

            canvas.drawLine(moveXOfFirst, getMoveY(moveXOfFirst),

                    moveXOfSecond, getMoveY(moveXOfSecond), paint);

        }

        float allEnergy = 0.0f; // 区域内的温度总和

        // 第一点小于第二点的情况

        if (moveXOfFirst < moveXOfSecond) {

            pointSpacing = Math.abs(moveXOfSecond - moveXOfFirst) / 2

                    + moveXOfFirst;

            // 得到两点间的 能量总计

            for (int j = moveXOfOne; j <= moveXOfTwo; j++) {

                allEnergy += energyItems.get(j).value;

            }

        }

        // 第一点大于第二点的情况

        if (moveXOfFirst > moveXOfSecond) {

            pointSpacing = Math.abs(moveXOfFirst - moveXOfSecond) / 2

                    + moveXOfSecond;

            for (int j = moveXOfTwo; j <= moveXOfOne; j++) {

                allEnergy += energyItems.get(j).value;

            }

        }

        // 第两点相等的情况

        if (moveXOfFirst == moveXOfSecond) {

            pointSpacing = Math.abs(moveXOfFirst);

        }

        // 绘制 移动的 点

        onPointMove(canvas, paint, moveXOfFirst, isDown);

        if (eventCount >= 2) {

            onPointMove(canvas, paint, moveXOfSecond, isDown);

        }

        // 绘制度数框 背景后的 横线

        canvas.drawBitmap(mTitleLine, SPACING, mGradientHeight + SPACING_HEIGHT

                - mTrendLine.getHeight() + 5, paint);

        // 顶部的度数框

        canvas.drawBitmap(mDegree, pointSpacing - mDegree.getWidth() / 2

                + mTrendLine.getWidth() / 2, (mGradientHeight + SPACING_HEIGHT

                - mTrendLine.getHeight() + 5) / 2, paint);

        // 绘制 总共消耗的能耗为多少

        String energyText = String.valueOf(allEnergy);

        int indexOf = energyText.indexOf(".");

        String substring = energyText.substring(0, indexOf + 2);

        paint.setTextSize(28);

        paint.setColor(Color.BLACK);

        canvas.drawText(substring + "度", pointSpacing - mDegree.getWidth() / 4,

                mGradientHeight + SPACING_HEIGHT - mTrendLine.getHeight()

                        + mDegree.getHeight() / 3, paint);

    }

源码下载:EnergyCurve.rar

 

你可能感兴趣的:(canvas)