Android自定義View-------Canvas動畫的誤解

前言

最近在看自定義View方面的知識,遇到下面一段代碼,由於對旋轉後的繪圖存在疑問,經過多方求證,最後彌補了操作Canvas(旋轉,平移等)認知的錯誤,並得出正確結論:

動畫操作Canvas,其實操作的是臨時座標系,對於已經繪製的圖形部分無效

下面詳細記錄求證過程,以備同仁指正:

建議大家按照代碼繪製看看,繪製對的可以留言,繪製錯了也可以留言,這篇博客讓你理解了嗎?

 /**
     * 在畫布的 左下角畫圓,
     * 中間畫向右箭頭 :旋轉畫布後再畫
     * 右上角畫圓:畫布旋轉爲原始方向後再畫
     * @param canvas
     */
    private void canvasTest(Canvas canvas) {
        int width = 200;
        int height = 200;
        int radius = 10;
        int centerX = radius;
        int centerY = height - radius;
        Paint paint = new Paint();
        //畫做左下角的圓
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.BLUE);
        paint.setAntiAlias(true);
        canvas.drawCircle(centerX, centerY, radius, paint);
        // 1.-------------------------------------------------------------
       canvas.save();
       canvas.rotate(90, width/2, height/2);   //以畫布中心爲旋轉點
//      canvas.translate(0, -30);
//      canvas.scale(1.2f, 1.2f, width/2, height/2);

        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);
        //左線、右線、中線, 把旋轉後的當做新畫布,但x, y 的座標仍是原來方向的,但畫出的圖是旋轉後的
        //可以想象爲先在原始畫布上畫,畫好後旋轉
        canvas.drawLine(width/2, 0, 0, height/2, paint);
        canvas.drawLine(width/2, 0, width, height/2, paint);
        canvas.drawLine(width/2, 0, width/2, height, paint);
        // 2.----------------------------------------------------
        canvas.restore();  //如果不加這一行,那麼下面的那個右上角的圓是 旋轉後的畫布的右上角,而非原始畫布的右上角位置
        //右上角畫個圓
        int cx2 = width - radius;
        int cy2 = radius;
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.RED);
        canvas.drawCircle(cx2, cy2, radius, paint);
    }

上述的代碼在我求證之初,我得出的圖形是這樣的:

錯誤的結果

既然是錯誤的,就不多解釋了,免得誤導大家。

下面是正確的繪圖結果:

這裏寫圖片描述

對比錯誤的和正確的繪圖,不難發現三點差異:

第一:座標系差異(這是個隱形的差異);

第二:旋轉前繪製的圓的差異(旋轉前繪製的圓到底該不該跟隨Canvas旋轉,爲什麼跟隨旋轉的是錯的呢?)

第三:最後一個圓的差異(這個差異其實是因爲第一個原因座標系的差異導致的);

接下來我們就對這三個差異一一解釋:

先說第二個,旋轉前繪製的圓的差異?

這個問題的原因就是我在最前面所說的:旋轉Canvas時,其實旋轉的是臨時的座標系,只對旋轉後的圖形有效,對旋轉前的繪圖無效。

接下來說第一個差異,最後一個圓繪製在canvas.restore()後面,此時的座標系還是旋轉後的座標系嗎?

答案是NO! canvas.restore()方法和canvas.save()方法,細心的朋友可以發現,我在前面特別表示了這兩個方法的位置,canvas.save()寫在旋轉之前,canvas.restore()方法就是將座標系恢復到sava方法調用的地方,所以他們是成雙成對出現的。

總結

動畫操作Canvas,其實操作的是臨時座標系,對於已經繪製的圖形部分無效。而Canvas.restore方法等於是將Canvas動畫操作還原成Save時的狀態

你對這個容易誤解的知識點掌握了嗎?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章