1

我需要动画绘制折线图。我将收到一组值(可能在 0 到 10 之间),并且随着时间的推移必须在图表上显示。我想要绘制折线图,​​并且绘图应该是可见的;动画。

我在这里查看了安德斯爱立信的教程:http ://www.jayway.com/2012/08/29/creating-custom-android-views-part-3-animating-your-custom-views-smoothly/#comment -105813

这里的代码:https ://github.com/andersericsson/ViewTutorialPart3

但我似乎无法按照自己的方式摆动它。

还有其他解决方案吗?

4

3 回答 3

1

我最终使用的解决方案涉及我扩展的课程中的一些代数View

该函数从活动中获取分数数组(值介于 0 和 10 之间),并使用 2×2 的值作为一行的起点和终点(注意,一行的终点是下一行的起点线)。

它计算线的长度以及线中有多少段;以及在该方向上移动多远x以及如何在该y方向上移动。

然后它计算线中第一段末端的x和值并绘制该段。y

然后将xDirectionand分别yDirection添加到xandy点并再次绘制线,现在包括线的第一段和第二段。对线中的每个线段都执行此操作,然后绘制从point Ato的最后一条线。point B

但这并不完整 - 函数中的全部for loop内容setData应该放在递归函数中,因为postInvalidateDelayed()不会暂停for loop执行。

但是,画布上根本没有绘制任何内容,因此链接到我目前在 SO 上的另一个问题:为什么在我的(自定义视图)画布上没有绘制线条?

但是对于这个问题,我认为我最终使用的解决方案可能还不错。注释?

public void setData(float[] scorePoints, float max, int totalScores){

    Log.d(TAG, "Get stuff from activity");

    scores = scorePoints;

    numberOfScores = totalScores;
    Log.d(TAG, "Number of scores = " + numberOfScores);

    maxScore = max;
    Log.d(TAG, "Max score = " + maxScore);

    segmentToDraw = (float) 10;

    //get the width of the area to draw
    width = Math.abs(getWidth() - getPaddingLeft() - getPaddingRight());        

    //get the height of the area to draw
    height = getHeight() - getPaddingTop() - getPaddingBottom();
    Log.d(TAG, "Drawable area in view = " + width + " x " + height);    

    /*
     * Now we start filling an array of points.
     * The onDraw function will drawLines of groupings of four points in a given array.
     *  
     * For the first segment, we'll draw from the x and y of the first point (which will be in the 1st and 2nd spots in our array)
     * to the x and y of the first segment (which will be in the 3rd and 4th spots in our array). 
     * And then the 3rd and 4th spots in our array will be replaced by a new x and y 
     * marking the end of the second segment to be drawn from our first point.
     * 
     * This will happen until the x and y is not smaller than the x and y of the final point of the line, any more.
     * Then the 3rd and 4th spots in our array will be replaced by the x and y of the final point of the line.
     * 
     * If there are more points to draw, the 5th and 6th spots in our array will also be created and filled with
     * the x and y of the final point of the line because it'll be the first two values (x and y) for drawing the next line.
     * 
     * So, yes, there will be duplicates in our array of points to draw, but a grouping of four spots will be used to draw one line,
     * and the end point of the first line is the starting point of the second line, so we need it twice.
     */     

    points.add(getXPos(scores[0]));
    points.add(getYPos(scores[0]));

    points.add((float) 0);
    points.add((float) 0);

    x = points.get(0);
    y = points.get(1);

    startPoint = scores[0];
    endPoint = scores[1];

    for(int i=0; i<scores.length-1; i++){
        String thePoints = "";

        if(i>0){

            startPoint = scores[i];
            endPoint = scores[i+1];             

            x = points.get(i*4);
            y = points.get((i*4) + 1);

        }

        startPointX = getXPos(startPoint);
        startPointY = getYPos(startPoint);

        endPointX = getXPos(endPoint);
        endPointY = getYPos(endPoint);

        distanceOfLine = (float) Math.sqrt(Math.pow((endPointX - startPointX), 2) + Math.pow((endPointY - startPointY), 2)); 
        Log.d(TAG, "Distance of line = " + distanceOfLine);

        //get number of segments in line
        numberOfSegmentsInLine = (int) (distanceOfLine/segmentToDraw);
        Log.d(TAG, "Number of segments in line = " + numberOfSegmentsInLine);

        //get distance to move in Y direction
        yDirection = (float) ((endPointY - startPointY)/ (float) numberOfSegmentsInLine);
        Log.d(TAG, "Move " + yDirection + " in Y direction");

        //get distance to move in X direction
        xDirection = (float) ((endPointX - startPointX)/ (float) numberOfSegmentsInLine);
        Log.d(TAG, "Move " + xDirection + " in X direction");


            //loop for each segment
            for(int j=0; j<numberOfSegmentsInLine; j++){
                x += xDirection;
                y += yDirection;                                        

                points.set(points.size()-2, Float.valueOf(x));
                points.set(points.size()-1, Float.valueOf(y));

                Log.d(TAG, "Line : " + (i+1) + " Segment : " + j);
                Log.d(TAG, "X = "+ (x+xDirection) + " Y = " + (y+yDirection));

                Log.d(TAG, "Call invalidate now!");
                //invalidate();
                //postInvalidateDelayed(delayMilliseconds);
            }               

            //draw final line
        points.set(points.size()-2, endPointX);
        points.set(points.size()-1, endPointY);

        invalidate();
        //postInvalidateDelayed(delayMilliseconds);

        if(i<scores.length-2){

            points.add(endPointX);
            points.add(endPointY);

            points.add((float) 0);
            points.add((float) 0);
        }           

        for(int k =0; k<points.size(); k++){
            thePoints = thePoints + " : " + points.get(k);
        }
        Log.d(TAG, "Points array = " + thePoints);
    }       
}

@Override
public void onDraw(Canvas canvas){
    //setWillNotDraw(true);

    Log.d(TAG, "DRAW DAMNIT!!!");
    Log.d(TAG, "Width = " + (int) width + " Height = " + (int)height);

    paint = new Paint();
    paint.setStyle(Style.STROKE);
    paint.setStrokeWidth(4);
    paint.setColor(Color.RED);
    //paint.setAntiAlias(true);
    //paint.setShadowLayer(4, 2, 2, 0x81000000);

    Bitmap bitmap = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
    canvas = new Canvas(bitmap);

    String drawPointsGo = "";
    float[] drawPoints = new float[points.size()];
    for(int i=0; i<points.size(); i++){
        Float f = points.get(i);
        drawPoints[i] = (float) (f != null ? f : 0.0);
        drawPointsGo = drawPointsGo + " : " + drawPoints[i];
    }
    Log.d(TAG, "Draw Points: " + drawPointsGo);

    canvas.drawLines(drawPoints, paint);
}
于 2013-06-19T13:30:00.043 回答
1

尝试查看 CountDownTimer 或 Runnable 以便 onTick() 或在发布时您可以通过绘制更多像素来更新您的行。这将让您一条接一条地绘制一条线,但会产生动画效果。

于 2013-08-15T20:06:02.993 回答
0

这是尝试的一般方向:

  1. 确保您对Canvas绘画感到满意。

  2. 然后你会想要创建一个新的View(子类它)并覆盖该onDraw方法。此方法应仅根据动画开始后经过的时间部分绘制图形。

于 2013-06-13T14:03:30.787 回答