<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 8.3.16 Canvas API詳解(Part 1) ## 本節引言: > 前面我們花了13小節詳細地講解了Android中Paint類大部分常用的API,本節開始我們來講解 Canvas(畫板)的一些常用API,我們在 > > * [8.3.1 三個繪圖工具類詳解](http://www.runoob.com/w3cnote/android-tutorial-drawable-tool.html "8.3.1 三個繪圖工具類詳解")中已經列出了我們可供調用的一些方法,我們分下類: > > * **drawXxx方法族**:以一定的坐標值在當前畫圖區域畫圖,另外圖層會疊加, 即后面繪畫的圖層會覆蓋前面繪畫的圖層。 > * **clipXXX方法族**:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個 畫圖區域就是canvas對象的當前畫圖區域了。比如:clipRect(new Rect()), 那么該矩形區域就是canvas的當前畫圖區域 > * **getXxx方法族**:獲得與Canvas相關一些值,比如寬高,屏幕密度等。 > * **save**(),**restore**(),**saveLayer**(),**restoreToCount**()等保存恢復圖層的方法 > * **translate**(平移),**scale**(縮放),**rotate**(旋轉),**skew**(傾斜) > > 當然還有其他一些零散的方法,嗯,從本節開始我會挑一些感覺有點意思的API來進行學習~ > > 而本節先給大家帶來的是**translate**(平移),**scale**(縮放),**rotate**(旋轉),**skew**(傾斜) 以及**save**(),**restore**()的詳解! > > 官方API文檔:[Canvas](http://androiddoc.qiniudn.com/reference/android/graphics/Canvas.html) > > 另外我們先要明確Canvas中X軸與Y軸的方向: > > ![](http://www.runoob.com/wp-content/uploads/2015/11/39871179.jpg) ## 1.translate(平移) > **方法**:**translate**(float dx, float dy) > > **解析**:平移,將畫布的**坐標原點**向左右方向移動x,向上下方向移動y,canvas默認位置在(0,0) > > **參數**:dx為水平方向的移動距離,dy為垂直方向的移動距離 **使用示例**: ``` for(int i=0; i < 5; i++) { canvas.drawCircle(50, 50, 50, mPaint); canvas.translate(100, 100); } ``` **運行效果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/67035226.jpg) ## 2.rotate(旋轉) > **方法**:**rotate**(float degrees) / **rotate**(float degrees, float px, float py) > > **解析**:圍繞坐標原點旋轉degrees度,值為正順時針 > > **參數**:degrees為旋轉角度,px和py為指定旋轉的中心點坐標(px,py) **使用示例**: ``` Rect rect = new Rect(50,0,150,50); canvas.translate(200, 200); for(int i = 0; i < 36;i++){ canvas.rotate(10); canvas.drawRect(rect, mPaint); } ``` **運行效果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/4328266.jpg) **代碼分析**: 這里我們先調用了translate(200,200)將canvas的坐標原點移向了(200,200),再進行繪制,所以我們 繪制的結果可以完整的在畫布上顯示出來,假如我們是為rotate設置了(10,200,200),會是這樣一個 結果: ![](http://www.runoob.com/wp-content/uploads/2015/11/69692038.jpg) 有疑問是吧,這個涉及到Canvas多圖層的概念,等等會講~ ## 3.scale(縮放) > **方法**:**scale**(float sx, float sy) / **scale**(float sx, float sy, float px, float py) > > **解析**:對畫布進行縮放 > > **參數**:sx為水平方向縮放比例,sy為豎直方向的縮放比例,px和py我也不知道,**小數為縮小**, **整數為放大** **使用示例**: ``` canvas.drawBitmap(bmp,0,0,mPaint); canvas.scale(0.8f, 0.8f); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.scale(0.8f, 0.8f); canvas.drawBitmap(bmp,0,0,mPaint); ``` **運行效果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/94500483.jpg) ## 4.skew(傾斜) > **方法**:**skew**(float sx, float sy) > > **解析**:傾斜,也可以譯作斜切,扭曲 > > **參數**:sx為x軸方向上傾斜的對應角度,sy為y軸方向上傾斜的對應角度,兩個值都是tan值哦! 都是tan值!都是tan值!比如要在x軸方向上傾斜60度,那么小數值對應:tan 60 = 根號3 = 1.732! **使用示例**: ``` canvas.drawBitmap(bmp,0,0,mPaint); canvas.translate(200, 200); canvas.skew(0.2f,-0.8f); canvas.drawBitmap(bmp,0,0,mPaint); ``` **運行效果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/84530658.jpg) ## 5.Canvas圖層的概念以及save()和restore()詳解 > 我們一般喜歡稱呼Canvas為畫布,童鞋們一直覺得Canvas就是一張簡單的畫紙,那么我想 問下多層的動畫是怎么用canvas來完成的?上面那個translate平移的例子,為什么 drawCircle(50, 50, 50, mPaint); 參考坐標一直是(50,50)那為何會出現這樣的效果? 有疑惑的童鞋可能是一直將屏幕的概念與Canvas的概念混淆了,下面我們來還原下 調用translate的案發現場: > > ![](http://www.runoob.com/wp-content/uploads/2015/11/91706861.jpg) > > 如圖,是畫布坐標原點的每次分別在x,y軸上移動100;那么假如我們要重新回到(0,0) 點處繪制新的圖形呢?怎么破,translate(-100,-100)的慢慢地平移回去?不會真的這么 糾結吧... > > ![](http://www.runoob.com/wp-content/uploads/2015/11/76166242.jpg) > > 好吧,不賣關子了,我們可以在做平移變換之前將當前canvas的狀態進行保存,其實Canvas為 我們提供了圖層(Layer)的支持,而這些Layer(圖層)是按"棧結構"來進行管理的 > > ![](http://www.runoob.com/wp-content/uploads/2015/11/45837171.jpg) > > 當我們調用**save()**方法,會保存當前Canvas的狀態然后作為一個Layer(圖層),添加到Canvas棧中, 另外,這個Layer(圖層)不是一個具體的類,就是一個概念性的東西而已! > > 而當我們調用**restore()**方法的時候,會恢復之前Canvas的狀態,而此時Canvas的圖層棧 會彈出棧頂的那個Layer,后繼的Layer來到棧頂,此時的Canvas回復到此棧頂時保存的Canvas狀態! > > 簡單說就是**:save()往棧壓入一個Layer,restore()彈出棧頂的一個Layer,這個Layer代表Canvas的 狀態!**也就是說可以save()多次,也可以restore()多次,但是restore的調用次數**不能大于**save 否則會引發錯誤!這是網上大部分的說法,不過實際測試中并沒有出現這樣的問題,即使我restore的 次數多于save,也沒有出現錯誤~目測是系統改了,等下測給大家看~ ![](http://www.runoob.com/wp-content/uploads/2015/11/89654180.jpg) 來來來,寫個例子驗證下save和restore的作用! **寫個例子**: **例子代碼**: ``` canvas.save(); //保存當前canvas的狀態 canvas.translate(100, 100); canvas.drawCircle(50, 50, 50, mPaint); canvas.restore(); //恢復保存的Canvas的狀態 canvas.drawCircle(50, 50, 50, mPaint); ``` **運行結果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/10539224.jpg) 不用說什么了吧,代碼和結果已經說明了一切,接著我們搞得復雜點,來一發 多個save()和restore()! **例子代碼:** ``` canvas.save(); canvas.translate(300, 300); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.rotate(45); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.rotate(45); canvas.drawBitmap(bmp, 0, 0, mPaint); canvas.save(); canvas.translate(0, 200); canvas.drawBitmap(bmp, 0, 0, mPaint); ``` **運行結果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/37911934.jpg) **結果分析**: 首先平移(300,300)畫圖,然后旋轉45度畫圖,再接著旋轉45度畫圖,接著平移(0,200), 期間每次畫圖前都save()一下,看到這里你可能有個疑問,最后這個平移不是y移動200 么,怎么變成向左了?嘿嘿,我會告訴你rotate()旋轉的是整個坐標軸么?坐標軸的 變化: ![](http://www.runoob.com/wp-content/uploads/2015/11/9381594.jpg) 嗯,rotate()弄懂了是吧,那就行,接著我們來試試restore咯~我們在最后繪圖的前面 加兩個restore()! ``` canvas.restore(); canvas.restore(); canvas.translate(0, 200); canvas.drawBitmap(bmp, 0, 0, mPaint); ``` **運行結果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/51696172.jpg) 不說什么,自己體會,再加多個**restore()**! ![](http://www.runoob.com/wp-content/uploads/2015/11/32919528.jpg) 有點意思,再來,繼續加**restore()** ![](http://www.runoob.com/wp-content/uploads/2015/11/84371338.jpg) 嗯,好像不可以再寫**restore**了是吧,因為我們只save了四次,按照網上的說法, 這會報錯的,真的是這樣嗎?這里我們調用Canvas給我們提供的一個獲得當前棧中 有多少個Layer的方法:**getSaveCount()**;然后在save()和restore()的前后都 加一個Log將棧中Layer的層數打印出來: ![](http://www.runoob.com/wp-content/uploads/2015/11/34631753.jpg) 結果真是喜聞樂見,畢竟實踐出真知,可能是Canvas改過吧,或者其他原因,這里 要看源碼才知道了,時間關系,這里我們知道下restore的次數可以比save多就好了, 但是還是建議restore的次數還是少于save,以避免造成不必要的問題~ 至于進棧和出棧的流程我就不話了,筆者自己動筆畫畫,非常容易理解! ## 6.saveLayer()與restoreToCount()講解 > 其實這兩個方法和save以及restore大同小異,只是在后者的基礎上多了一些東東而已, 比如saveLayer(),有下面多個重載方法: > > ![](http://www.runoob.com/wp-content/uploads/2015/11/47364992.jpg) > > 你可以理解為**save()**方法保存的是**整個Canvas**,而saveLayer()則可以選擇性的保存某個區域的狀態, 另外,我們看到餐宿和中有個:**int saveFlags**,這個是設置改保存那個對象的!可選值有: | 標記 | 說明 | | :-- | :-- | | **ALL_SAVE_FLAG** | 保存全部的狀態 | | **CLIP_SAVE_FLAG** | 保存裁剪的某個區域的狀態 | | **CLIP_TO_LAYER_SAVE_FLAG** | 保存預先設置的范圍里的狀態 | | **FULL_COLOR_LAYER_SAVE_FLAG** | 保存彩色涂層 | | **HAS_ALPHA_LAYER_SAVE_FLAG** | 不透明圖層保存 | | **MATRIX_SAVE_FLAG** | Matrix信息(translate,rotate,scale,skew)的狀態保存 | PS:上述說明有點問題,筆者英語水平低,可能說錯,如果有知道的,請務必指正提出,謝謝~ 這里我們寫個例子來驗證下:我們選用**CLIP_TO_LAYER_SAVE_FLAG**模式來寫個例子 **實現代碼**: ``` RectF bounds = new RectF(0, 0, 400, 400); canvas.saveLayer(bounds, mPaint, Canvas.CLIP_TO_LAYER_SAVE_FLAG); canvas.drawColor(getResources().getColor(R.color.moss_tide)); canvas.drawBitmap(bmp, 200, 200, mPaint); canvas.restoreToCount(1); canvas.drawBitmap(bmp, 300, 200, mPaint); ``` **運行結果**: ![](http://www.runoob.com/wp-content/uploads/2015/11/45193934.jpg) 關于saveLayer()后面用到再詳解研究吧~這里先知道個大概~ 接著到這個**restoreToCount(int)**,這個更簡單,直接傳入要恢復到的Layer層數, 直接就跳到對應的那一層,同時會將該層上面所有的Layer踢出棧,讓該層 成為棧頂~!比起你寫多個restore()方便快捷多了~ ## 7.本節代碼示例下載: 嗯,代碼是寫著測試的,要來也沒多大意思,不過可能讀者還是想要,就貼下鏈接吧! **代碼下載**:[CanvasDemo.zip](http://static.runoob.com/download/CanvasDemo.zip) 可能你們要的是這個圖吧!哈哈~ ![](http://www.runoob.com/wp-content/uploads/2015/11/88655895.jpg) ## 本節小結: > 本節是糾結了幾天才寫出來的,因為筆者一開始對這個Canvas圖層的概念也不是很清晰, 今天下午做完事捋了捋思路,晚上再加加班終于把這篇東西寫出來了,相信應該能幫助 大家更清楚的理解Canvas,進階自定義控件時也不會一頭霧水~嘿嘿,本節就到這里, 如果有寫錯的地方歡迎提出,萬分感謝~![](http://www.runoob.com/wp-content/uploads/2015/11/79610477.jpg) **參考文獻**: [AndroidのCanvasを使いこなす! – 基本的な描畫](http://tech.recruit-mp.co.jp/mobile/remember_canvas1/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看