如何为在Android中绘制的图形设置动画

时间:2013-06-13 13:37:27

标签: android animation graph

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

我在这里查看了Anders Ericsson的教程: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

但我似乎无法摆动它以我的方式工作。

那里有另一种解决方案吗?

3 个答案:

答案 0 :(得分:1)

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

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

它计算线条的长度以及线条中的线条数量;还有x方向移动的距离以及如何沿y方向移动。

然后,它计算行中第一个段的结尾的xy值,并绘制该段。

然后xDirectionyDirection分别添加到xy点,然后再次绘制线条,现在包括第一段和第二段线。这是针对该行中的每个片段完成的,然后绘制从point Apoint B的最后一行。

但它并不完整 - for loop函数中的整个setData应放在递归函数中,因为postInvalidateDelayed()不会暂停执行for loop

但是,画布上根本没有画出任何内容,因此链接到我目前在SO上的另一个问题:Why are no lines drawn on my (custom View) canvas?

但对于这个问题,我认为我最终使用的解决方案可能并不那么糟糕。评论

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);
}

答案 1 :(得分:1)

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

答案 2 :(得分:0)

以下是尝试的一般方向:

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

  2. 然后,您将需要创建一个新的View(它的子类)并覆盖onDraw方法。 此方法应仅根据动画开始后的elapsed time部分绘制图形。