Android线性曲线视图

来源:互联网 发布:linux 机器重启时间 编辑:程序博客网 时间:2024/06/08 18:23
/**
 *线性曲线视图
 */
public class LineGraphView extends GraphView {

    private enum Action{NONE, DOWN, MOVE, UP}
    private Enum gesture = Action.NONE;

    private static final int DEFAULT_LAST_X = -100;

    private final Paint paintBackground;
    private boolean drawBackground;

    private Paint mPathPaint = new Paint();
    private Paint mPathAreaPaint = new Paint();
    private Paint mPointPaint = new Paint();
    private Paint mPointPaint2 = new Paint();
    private Path mGraphLine = new Path();
    private Bitmap brick;
    private Bitmap line = BitmapFactory.decodeResource(getResources(), R.drawable.com_graph_line_long1);
    private LinearGradient lg;

    private int mLastX = DEFAULT_LAST_X;
    private int mLastY;
    private int mDx;//手势X轴间距
    private int bkColor;

    private boolean mCircleFlow = false;//圆是否跟随砖头滑动

    private boolean mShowBrick = true;
    public float midX;

    public boolean isDrawPoint=true;//是否画圆点
    public Map<String,Float[]> map;
    public float lastX;//记录第一条曲线的X的最大值

    private OnBrickMoveListener obml;
    
    private boolean onClickDown = false;//是否点趋势图下钻
    

    private Runnable showBrickRunnable = new Runnable() {

        @Override
        public void run() {

            if(!mShowBrick){
                drawSomethingLayout.setVisibility(View.INVISIBLE);
            }


        }
    };


    public LineGraphView(Context context) {
        super(context);
        paintBackground = new Paint();
        paintBackground.setStrokeWidth(4);
        setClickable(true);
        setFocusable(true);

        mPathPaint.setAntiAlias(true);
        mPathPaint.setColor(Color.BLUE);
        mPathPaint.setStyle(Paint.Style.STROKE);

        mPathAreaPaint.setAntiAlias(true);
        mPathAreaPaint.setDither(true);
        mPathAreaPaint.setColor(Color.BLUE);
        mPathAreaPaint.setAlpha(128);
        mPathAreaPaint.setStyle(Paint.Style.FILL);

        mPointPaint.setAntiAlias(true);
        mPointPaint.setDither(true);
        mPointPaint.setStyle(Paint.Style.FILL);
        mPointPaint.setStrokeCap(Cap.ROUND);
        mPointPaint.setStrokeJoin(Join.ROUND);

    }



    @Override
    public void drawSomething(Canvas canvas, float graphwidth, float graphheight, double minX, double minY, double diffX, double diffY, float horstart) {
//        long a = System.currentTimeMillis();
        for(int t=0;t<mGraph.size();t++){
            GraphData[] values = mGraph.get(t).values;

            //如果绘制区域超出第一条线
//            if(mLastX > graphwidth / getXSize() * values.length){
//                for(Graph g : mGraph){
//                    if(g.values.length == getXSize()){
//                        values = g.values;
//                        break;
//                    }
//                }
//            }

            if(mLastX == DEFAULT_LAST_X && values.length != 0){
                mLastX = (int)(horstart + (graphwidth / diffX * values[values.length - 1].getValueX()));
//                Log.i("初始值", "mLastX  = "+mLastX+"   horstart  = "+horstart+"  graphwidth = "+graphwidth+"   "+getWidth());
            }
//            final int bottom = getBottom();
            //判断边界,画线
            int left = (int)Math.min(Math.max(mLastX, horstart), getWidth()-dx);
            paint.setColor(0XFFFD7F7F);
            //canvas.drawLine(left, top, left, bottom, paint);
            float scaleY=1;
            if(line.getHeight()!=graphheight){//-brick.getHeight()
                scaleY = (graphheight)/line.getHeight();//-brick.getHeight()
            }

            Matrix m = new Matrix();
            m.postScale(1, scaleY);
            Bitmap line1 = Bitmap.createBitmap(line, 0, 0, line.getWidth(), line.getHeight(), m, true);
//            System.out.println("line.height = "+line.getHeight()+"  graphheight = "+graphheight+"   left = "+left+"  mLastX = "+mLastX);

//            final float top = graphheight-line1.getHeight()-dy;
//            if(t==0 && !onClickDown){
//                if(left>=horstart && left <=graphwidth + horstart){
//                canvas.drawBitmap(line1, left - line1.getWidth() / 2, top, paint);
//                }else if(left<horstart){
//                    canvas.drawBitmap(line1, horstart - line1.getWidth() / 2, top, paint);
//                }else{
//                    canvas.drawBitmap(line1, graphwidth + horstart - line1.getWidth() / 2, top, paint);
//                }
//                //        System.out.println("left = = "+left);
//            }
            double lastEndY = 0;
            double lastEndX = horstart;

            float pointY = -10f;
            float pointX = -10f;
            String hint = (values.length == 0) ? "" : values[0].getStringValueY()+values[0].getUnit();
            int brickDataIndex = 0;

            for (int i = 0; i < values.length; i++) {
                double valY = values[i].getValueY() - minY;
                double ratY = valY / diffY;
                double y = graphheight * ratY - dy;

                double valX = values[i].getValueX() - minX;
                double ratX = valX / diffX;
                double x = graphwidth * ratX + horstart;

                if (i > 0) {
                    float startX = (float) lastEndX;
                    float startY = (float) (-lastEndY) + graphheight;
                    float endX = (float) x ;
                    float endY = (float) (- y) + graphheight;
//                    Log.i("startX>>>>>>>>>>", "startX   "+startX+"   endX = "+endX+"   mLastX  = "+mLastX+"  mDx = "+mDx);
                    if(startX <= mLastX && mLastX <= endX){

                        hint = values[i - 1].getStringValueY()+values[0].getUnit();
                        brickDataIndex = i - 1;
                        //计算圆点圆心
                        float scale = (mLastX - startX) / (endX - startX);
                        midX=(endX - startX)/2;
                        if(mCircleFlow){
                            pointY = startY + (endY - startY) * scale;
                            pointX = mLastX;
                            if(mDx <0){
                                hint = values[i].getStringValueY()+values[0].getUnit();
                                brickDataIndex = i;
                            }
                        }else{
                            pointY = startY;
                            pointX = startX;
                            if((mDx >=0&&(mLastX - startX)>midX)||(mDx <=0&&(mLastX - startX)>midX)&&(mLastX>midX*2+2)){
                                hint = values[i].getStringValueY()+values[0].getUnit();
                                brickDataIndex = i;
                                pointX = endX;
                                pointY = endY;
                            }else{
                                hint = values[i-1].getStringValueY()+values[0].getUnit();
                                brickDataIndex = i-1;
                                pointX = startX;
                                pointY = startY;
                            }
                        }
                    }else if(mLastX < horstart){
                        pointY = startY;
                        pointX = startX;
                        hint = values[0].getStringValueY()+values[0].getUnit();
                        break;
                    }else if(mLastX >= endX){
                        pointY = endY;
                        pointX = endX;
                        hint = values[i].getStringValueY()+values[0].getUnit();
                        brickDataIndex = i;
                    }
                }
                lastEndY = y;
                lastEndX = x;    
//                Log.i("pointX", mLastX+"  pointX = "+pointX+"  lastEndX = "+lastEndX);
            }
//                    Log.i("brickDataIndex", brickDataIndex+">>>>>>"+"   mLastX = "+mLastX+"  pointX = "+pointX+"  pointY = "+pointY);
            if(obml != null){
                obml.onMove(brickDataIndex);
                if(gesture == Action.UP){
                    obml.onStop(brickDataIndex);
                }
            }

//            final int halfW = brick.getWidth() / 2;
//            int tx = mLastX - halfW;
//            final int ty = brick.getHeight() / 2;
//
//            if(mLastX < halfW){
//                tx = 0;
//            }else if(mLastX > getWidth() - halfW){
//                tx = getWidth() - brick.getWidth();
//            }
//
//            //画砖头
//            canvas.drawBitmap(brick, tx, getTop(), paint);
//            //        System.out.println("mLastX = "+mLastX+"  tx = "+tx+"  brick.getWidth() / 2="+halfW);
//
//            //画砖头文阴影
            mPointPaint.setStrokeWidth(0);
            mPointPaint.setColor(0xFF000000);
            mPointPaint.setTextAlign(Align.CENTER);
            final int txtSize = 20;
            mPointPaint.setTextSize(txtSize);
//            canvas.drawText(hint, tx + halfW + 1, ty + txtSize / 2 + 1, mPointPaint);
//            //画砖头文
//            mPointPaint.setColor(0XFF888888);
//            canvas.drawText(hint, tx + halfW, ty + txtSize / 2-2 , mPointPaint);
//            canvas.drawText(hint,(float)pointX, pointY-5, mPointPaint);

            final float top = graphheight-line1.getHeight() + dy;
            if(t==0 && !onClickDown){
                if(left>=horstart && left <=graphwidth + horstart){
                    canvas.drawBitmap(line1, pointX - line1.getWidth() / 2, top, paint);
                }else if(left<horstart){
                    canvas.drawBitmap(line1, horstart - line1.getWidth() / 2, top, paint);
                }else{
                    canvas.drawBitmap(line1, graphwidth + horstart - line1.getWidth() / 2, top, paint);
                }
                //        System.out.println("left = = "+left);
            }

            if(!onClickDown){
    //            if(mLastX > 0 && mLastX < graphwidth){
                    //画外圆
                    mPointPaint.setStrokeWidth(mPointSize);
                    mPointPaint.setColor(mPointColor);
                    canvas.drawPoint((float)pointX, pointY, mPointPaint);
                    //画内圆
                    mPointPaint.setStrokeWidth(mPointSize/3*2);
                    mPointPaint.setColor(0XFFFFFFFF);
                    canvas.drawPoint((float)pointX, pointY, mPointPaint);
    //            }
            }
            
//            long b = System.currentTimeMillis();
//            System.out.println("drawSomeThing spend " + (b - a) + " mills.");
        }
    }


    /**
     * 绘制曲线图
     * @param vanvas 画布
     * @param values 画图所需数据集合
     * @param grapwidth 曲线视图宽
     * @param grapheight 曲线视图高
     * @param border
     */
    @Override
    public void drawSeries(Canvas canvas, int index, float graphwidth, float graphheight, double minX, double minY, double diffX, double diffY, float horstart) {
//        long a = System.currentTimeMillis();
//        Log.i("a>>>>>>>", a+">>>>>>>>>>");
        final GraphData[] values = mGraph.get(index).values;
        map=new HashMap<String,Float[]>();
        //画曲线
        for (int i = 0; i < values.length; i++) {
            double valY = values[i].getValueY() - minY;
            double ratY = valY / diffY;
            double y = graphheight * ratY - dy;
//            Log.i("y>>>>>>>", y+">>>>>>>>>>");
            double valX = values[i].getValueX() - minX;
            double ratX = valX / diffX;
            double x = graphwidth * ratX + horstart;

            if (i > 0) {
                float endX = (float) x +  1;
                float endY = (float) (- y) + graphheight;
                mGraphLine.lineTo(endX, endY);
                if(isDrawPoint){
                    map.put(i+"", new Float[]{endX-1,endY});
                }
            }else{
                mGraphLine.rewind();
                final float startX = horstart;
                final float startY = (float)(- y) + graphheight;
                mGraphLine.moveTo(startX, startY);
                if(isDrawPoint){
                    map.put(i+"", new Float[]{startX,startY});
                }
            }
        }

        if(isDrawPoint){
            mPointPaint2.setTextSize(13);
            mPointPaint2.setStyle(Paint.Style.STROKE);
            mPointPaint2.setAntiAlias(true);
            mPointPaint2.setDither(true);
            mPointPaint2.setStyle(Paint.Style.FILL);
            mPointPaint2.setStrokeCap(Cap.ROUND);
            mPointPaint2.setStrokeJoin(Join.ROUND);
            //每个曲线折点的圆点
            for(int i=0;i<map.size();i++)
            {
                Float[] point=map.get(i+"");
                //画外圆
                mPointPaint2.setStrokeWidth(mPointSize);
                mPointPaint2.setColor(0X1FFFFFFF);
                canvas.drawPoint(point[0], point[1], mPointPaint2);
                //画内圆
                mPointPaint2.setStrokeWidth(mPointSize/2);
                mPointPaint2.setColor(mGraph.get(index).color);
                canvas.drawPoint(point[0], point[1], mPointPaint2);
                if(index==0&&i==map.size()-1)
                    lastX=point[0];
//                String txt = (int)values[i].getValueY()+"";
//                mPointPaint2.setColor(Color.BLACK);
//                canvas.drawText(txt, point[0]-mPointPaint2.getTextSize()/2, point[1]-3, mPointPaint2);
            }
        }
        mPathPaint.setStyle(Paint.Style.STROKE);
        mPathPaint.setStrokeWidth(mPointSize/6);
        mPathPaint.setColor(mGraph.get(index).color);
        canvas.drawPath(mGraphLine, mPathPaint);

        //画曲线背景
        if(drawBackground){
            mGraphLine.lineTo(graphwidth, graphheight-dy);
            mGraphLine.lineTo(0, graphheight-dy);
            mGraphLine.close();
            if(lg == null){
                lg= new LinearGradient(0,0,0,getHeight(),new int[]{bkColor,Color.WHITE},  
                        null,Shader.TileMode.CLAMP);
            }
            mPathAreaPaint.setShader(lg);
            canvas.drawPath(mGraphLine, mPathAreaPaint);
        }
//        long b = System.currentTimeMillis();
        //        System.out.println("drawSeries spend " + (b - a) + " mills.   "+bkColor);
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //获得触碰手指个数
        final int point = event.getPointerCount();

        if(point == 1 && !onClickDown){
            final int x = (int)event.getX();
            final int y = (int)event.getY();
            final int action = event.getAction();
//                        System.out.println("MOVE  x = "+x+"y = "+y);
            switch(action){

            case MotionEvent.ACTION_MOVE:
                gesture = Action.MOVE;
//                                System.out.println(" Action.MOVE  mLastX="+mLastX);
                if(Math.abs(event.getX() - mLastX) > 1.5f){
                    if(Math.abs(x - mLastX) > 0){
                        mDx = x - mLastX;
                        mLastX = x;
                        mLastY = y;
                        drawSomethingLayout.getChildAt(0).invalidate();
//                        System.out.println(" Action.  drawSomethingLayout.invalidate()");
                    }
                }

                break;
            case MotionEvent.ACTION_DOWN:
                gesture = Action.DOWN;
                mLastX = x;
                mLastY = y;
                //取消Post
                removeCallbacks(showBrickRunnable);
                if(drawSomethingLayout.getVisibility() == View.INVISIBLE){
                    drawSomethingLayout.setVisibility(View.VISIBLE);
                }
                drawSomethingLayout.getChildAt(0).invalidate();
                if (getParent() != null) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }

                break;
            case MotionEvent.ACTION_UP:
                gesture = Action.UP;
                mLastX = x;
                mLastY = y;
                drawSomethingLayout.getChildAt(0).invalidate();
//                System.out.println(" Action.ACTION_UP  mLastX="+mLastX);
                postDelayed(showBrickRunnable, 2000);
                if (getParent() != null) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                break;
            }

        }
        return !onClickDown;
//        return super.onTouchEvent(event);
    }

    public boolean isDrawBackground() {
        return drawBackground;
    }

    /**
     * 是否填充曲线背景
     * @param color 背景渐变色
     */
    public void setDrawBackground(boolean drawBackground, int color) {
        this.drawBackground = drawBackground;
        this.bkColor = color;
    }

    /**
     * 设置砖头的图案
     */
    public void setBrickResource(int resId){
        Options op = new Options();
        op.inScaled = false;
        brick = BitmapFactory.decodeResource(getResources(), resId, op);
    }

    public void setBrickBitmap(Bitmap bmp){
        brick = bmp;
    }


    /**
     * 圆点是否跟随砖头移动
     * @return
     */
    public boolean ismCircleFlow() {
        return mCircleFlow;
    }

    /**
     * 圆点是否跟随砖头移动
     * @param mCircleFlow
     */
    public void setCircleFlow(boolean mCircleFlow) {
        this.mCircleFlow = mCircleFlow;
    }

    /**
     * 设置砖头移动监听
     * @param obml
     */
    public void setOnBrickMoveListener(OnBrickMoveListener obml){
        this.obml = obml;
    }


    /**
     * 砖头移动监听
     * @author Administrator
     *
     */
    public interface OnBrickMoveListener{

        /**
         * @param graphIndex 曲线的索引
         * @param graphDataIndex 曲线的第几条数据
         * @param data 该条数据
         */
        public void onMove(int graphDataIndex);


        public void onStop(int graphDataIndex);
    }

    public boolean isOnClickDown() {
        return onClickDown;
    }



    public void setOnClickDown(boolean onClickDown) {
        this.onClickDown = onClickDown;
    }

}

原创粉丝点击