canvas.clipRect操作在android6上繪圖正常但在android9不正常的原因

編者:李國帥

qq:9611153 微信lgs9611153

時間 2020/6/17

背景原因:

android繪圖的方法有很多種,比如opengl,sdl, canvas,surfaceview canvas等,不過對於簡單繪圖功能,使用canvas就足夠了。

 

幾天前,遇到了一個問題,以前在android6.0設備上能夠正常繪圖的程序在android9.0手機上突然就不行了。

解決這個問題的過程中依次排除了函數兼容性錯誤,硬件加速等錯誤,最後才鎖定問題。

 

所需資源:

Android,canvas繪圖

 

解決過程:

首先修改了明顯的語法錯誤:

   if(Build.VERSION.SDK_INT >= 26){

        m_memCanvas.clipRect(left, top, right, bottom);

    }else {

        m_memCanvas.clipRect(left, top, right, bottom, Region.Op.UNION);

    }

Canvas.clipRect:在手機屏幕上裁剪出一塊區域來,起點是從屏幕的左上角開始。

更改了也沒有效果,說明這不是簡單的兼容性問題。

 

然後,發現還是有問題,圖像顯示不正常。

查了網上的資料,有人說是硬件加速的問題,於是添加了相關語句。

        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);//禁止硬件加速 sdk 29

還有其他禁止硬件加速的方法,都試了,依然如故,說明還是沒有找對方法。

禁止加速不行,那就是其他原因。

 

也不是canvas函數不起作用,因爲新編寫的例子都是正常的。

 

仔細觀察,發現canvas執行drawPath的時候是能夠顯示一個小區域。所以可能是與clipRect函數有關。

於是打印出clipRect的區域和path中lineto畫線的區域,一切都是正常對應的,不存在繪製到無效區域的情況

 

到底是爲什麼呢?

仔細觀察對比正常繪圖與不正常繪圖,發現當前代碼中,每次進行裁剪之前進行了canvas.save();但是在繪圖之後卻沒有調用restore()。

是這個原因嗎?

 

save() : 用來保存Canvas的狀態,save()方法之後的代碼,可以調用Canvas的平移、放縮、旋轉、裁剪等操作!

 

restore():用來恢復Canvas之前保存的狀態(可以想成是保存座標軸的狀態),防止save()方法代碼之後對Canvas執行的操作,繼續對後續的繪製會產生影響,通過該方法可以避免連帶的影響

 

通過測試,在加入restore()之後,發現在android 9上面依然是可以顯示繪圖的

 

正確的做法:

 

使用裁剪clip繪圖的流程必須是:

 canvas.save()----canvas.clipRect----canvas.draw--- canvas.restore();

整個流程一個步驟都不能少。

canvas.save();

canvas.clipRect(object_x, object_y, object_x + object_width, object_y + object_height);

canvas.drawBitmap(boosPlaneBomb, object_x, object_y - y, paint);

canvas.restore();

 

正確的流程才能保證正常的功能和願景。

總結:

說到底,這依然是個兼容性問題。

對於老版本的android sdk,如果沒有調用canvas.restore()直接調用canvas.clipRect會使用新的裁剪區域,但是新版本不行。

 

所謂的一朝天子一朝臣,不同的SDK版本採用不同規範(語言的,業務的),排除方式。

當系統或者底層sdk發生變化的時候,可能會引起依賴於他們的上層軟件發生相應的變化

這就是爲什麼以前的軟件用得好好的,升級之後突然就不行了的原因。

 

32位計算機的時候,16位程序不能用了;系統升級後,許多系統工具不能用了。語言升級後,許多代碼不能用了。

不要老是想後看,世界總是滾滾向前。

 

語言升級問題

語言也是不斷的發展,嚴謹程度,開發效率,易用程度都在變化。

語言開發包原來的語法,用法可能不嚴謹,不規範。語言升級後,基於此的代碼也可能出現兼容性問題。

 

如在VC6中

for(int i=0;i<10;i++);

for(i=0;i<10;i++);

是正確的的,可以編譯的,但是在新版本VC中則是錯誤的。這個問題編譯過directshow源碼的朋友應該很清楚。

 

那些成熟的應用廣泛的sdk錯誤很少,但是並不代表沒有錯誤,而且隨着sdk的更新發展,以及所有規範的變遷,都在不停的完善。

 

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