Andriod中繪(畫)圖----Canvas的使用詳解
由於在網路上找到關於Canvas的使用都比較抽象,也許是我的邏輯思維不太好吧,總是感覺理解起來比較困難,
尤其是對save()和restore()方法的使用。本篇文章的內容就是對Canvas的使用進行一下總結,包括它的兩種不同的使用
情節和它的一些方法進行一下說明。
1 Bitmap,可以來自資源/檔案,也可以在程式中建立,實際上的功能相當於圖片的儲存空間;
2 Canvas,緊密與Bitmap聯絡,把Bitmap比喻內容的話,那麼Canvas就是提供了眾多方法操作Bitamp的平臺;
3 Paint,與Canvas緊密聯絡,是"畫板"上的筆刷工具,也用於設定View控制元件上的樣式;
4 Drawable,如果說前三者是看不見地在記憶體中畫圖(虛擬的),那麼Drawable就是把前三者繪圖結果表現出來的介面(真實的)。
Drawable多個子類,例如:點陣圖(BitmapDrawable)、圖形(ShapeDrawable)、圖層(LayerDrawable)等。
我們打個簡單的比方吧:
Paint 就是畫筆
Bitmap 就是畫布
Canvas 就是畫家
於是,畫家可以通過畫筆可以在畫布上進行任何的畫畫。
Canvas的兩種使用情形,從Canvas物件的獲得角度分析:
1、 自定義View和自定義SurfaceView中獲得Canvas物件
由於自定義View和SurfaceView在顯示介面中已經獲得了顯示區域,canvas物件只不過是在其顯示(繪畫)區域進行介面佈局
的設計,當操作完畢後,系統會顯示canvas的操作結果。
自定義View的繪圖方法為:
//存在canvas物件,即存在預設的顯示區域
@Override
public void draw(Canvas canvas) {
//canvas繪圖
}
SurfaceView的繪圖方法為,例如:
SurfaceView surfaceView = new MySurfaceView() ; //建立一個Surface物件
SurfaceHolder surfaceHolder = surfaceView. getHolder() ; //獲得SurfaceHolder物件
Canvas canvas = surfaceHolder.lockCanvas() ; //獲得canvas物件
//進行繪圖操作
surfaceHolder.unlockCanvasAndPost(canvas) ; //釋放canvas鎖,並且顯示檢視
2、 在其他情形下,我們需要通過程式碼建立一個Canvas物件,並且在繪畫成功後,將該畫圖區域轉換為Drawable圖片
或者通過setBitmap(bitmap)顯現出來。一般步驟為:
//建立一個的Bitmap物件
Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888) ;
//建立一個canvas物件,並且開始繪圖
Canvas canvas = new Canvas (bitmap) ;
ImageView imgView = new ImageView(this) ; //或者其他可以設定背景圖片的View控制元件
//為ImageView設定影象
//將Bitmap物件轉換為Drawable影象資
Drawable drawable = new BitmapDrawable(bitmap) ;
imgView .setBackgroundDrawable(drawable) ;
或者簡單點: imgView .setImageBitmap(bitmap);
這兩種方式都可以顯示我們的繪圖。
Canvas方法分析:
clipXXX()方法族
說明:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個畫圖區域就是canvas物件的當前畫圖區域了。
例如:clipRect(new Rect()),那麼該矩形區域就是canvas的當前畫圖區域了。
public int save()
說明:儲存已經由canvas繪畫出來的東西,在save()和restore()方法之間的操作不對它們造成影響,例如旋轉(roate)等。
而且對canvas的操作(roate和translate)都是臨時的,restore()後不再存在。
public voidrestore()
說明:復原sava()方法之前儲存的東西資源。
drawXXX()方法族
說明:以一定的座標值在當前畫圖區域畫圖。
注意:圖層會疊加,即後面繪畫的圖層會覆蓋前面繪畫的圖層。
需要注意的方法是:
public voiddrawRect(float left, float top, float right, float bottom,Paint paint)
說明:繪製一個矩型。需要注明的是繪製矩形的引數和Java中的方法不一樣。
該方法的引數圖解說明如下:
各位看官請注意:圖中X、Y軸方向標記錯誤。 自己也懶得重新修正了。
那麼,矩形的高 height = bottom - right
矩形的寬 width = right – left
PS :假如drawRect的引數有誤,比如right < left ,Android是不會給我們檢查的,也不會提示相應的錯誤資訊,
但它會繪畫出一個高或寬很小的矩形,可能不是你希望的。
public voidtranslate(float dx, float dy)
說明:在當前的座標上平移(x,y)個畫素單位
若dx <0 ,沿x軸向上平移; dx >0 沿x軸向下平移
若dy <0 ,沿y軸向上平移; dy >0 沿y軸向下平移
public void rotate(float degrees)
說明:旋轉一定的角度繪製圖像。
PS :從截圖上看,影象是確實旋轉了,但是我找不到旋轉的依據中心。
下面給出該Demo的截圖,可以更改一些引數後自己觀察效果。
1、佈局檔案 main.xkl : 採用了兩個ImageView來顯示bitmap繪圖物件, 讓後採用了一個自定義View繪圖
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="顯示canvas區域以及clip方法的使用" />
<ImageView android:id="@+id/imgClip" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_marginTop="10dip" />
<View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="save方法和restore方法的使用" />
<ImageView android:id="@+id/imgSave" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_marginTop="10dip" />
<View android:layout_width="fill_parent" android:layout_height="2dip" android:background="#800080" android:layout_marginTop="2dip"></View>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="自定義View,獲得了一個Canvas物件和繪圖區域" />
<com.qin.canvas.MyView android:id="@+id/myView"
android:layout_width="fill_parent" android:layout_height="200px" />
</LinearLayout>
2、自定義View , MyView.java,
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Bitmap.Config;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View{
private Paint paint = new Paint() ;
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyView(Context context , AttributeSet attrs){
super(context,attrs);
}
//存在canvas物件,即存在預設的顯示區域
@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
super.draw(canvas);
//加粗
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
paint.setColor(Color.BLUE);
canvas.drawText("自定義View,canvas物件已經存在。", 30, 40, paint);
canvas.drawRect(10, 10, 30, 30, paint);
//將icon影象轉換為Bitmap物件
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;
canvas.drawBitmap(iconbit, 40,40, paint);
}
}
3、主工程檔案 MainActivity.java
public class MainActivity extends Activity {
//畫筆物件 paint
private Paint paint = new Paint() ; //記得要為paint設定顏色,否則 看不到效果
private ImageView imgClip ; // 繪圖區域以及clip方法
private ImageView imgSave ; // save方法以及restore
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main) ;
imgClip = (ImageView)findViewById(R.id.imgClip) ;
imgSave = (ImageView)findViewById(R.id.imgSave);
clip_drawCanvas() ; // 繪圖區域以及clip方法
save_drawCanvas(); // save方法以及restore
}
//這樣的情況下,需要建立Canvas物件,然後在此物件上進行操作
//對bitmap操作完成後,,顯示該Bitmap有以下兩種操作。
//1、需要將bitmap轉換為Drawable物件 Drawable drawable = new BitmapDrawable(bitmap) ;
//2、直接setImageBitmap(bitmap)
private void clip_drawCanvas(){
//將icon影象轉換為Bitmap物件
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;
//建立一個的Bitmap物件
Bitmap bitmap = Bitmap.createBitmap(200, 150, Config.ARGB_8888) ;
Canvas canvas = new Canvas (bitmap) ;
//設定顏色來顯示畫圖區域
canvas.drawColor(Color.RED);
paint.setColor(Color.BLACK);
canvas.drawText("原先的畫圖區域--紅色部分", 60,50,paint) ;
//畫bitmap物件
canvas.drawBitmap(iconbit, 20, 20, paint);
//剪裁一個區域,當前的操作物件為Rect裁剪的區域
Rect rect = new Rect (10,80,180,120) ;
//當前的畫圖區域為Rect裁剪的區域,而不是我們之前賦值的bitmap
canvas.clipRect(rect) ;
canvas.drawColor(Color.YELLOW);
//設定顏色來顯示畫圖區域
paint.setColor(Color.BLACK);
canvas.drawText("裁剪clip後畫圖區域-黃色部分", 10,100,paint) ;
//將Bitmap物件轉換為Drawable影象資源
//Drawable drawable = new BitmapDrawable(bitmap) ;
//img.setBackgroundDrawable(drawable) ;
//顯示,同上
imgClip.setImageBitmap(bitmap);
}
private void save_drawCanvas(){
//將icon影象轉換為Bitmap物件
Bitmap iconbit = BitmapFactory.decodeResource(getResources(), R.drawable.icon) ;
//建立一個的Bitmap物件
Bitmap bitmap = Bitmap.createBitmap(200, 100, Config.ARGB_8888) ;
Canvas canvas = new Canvas (bitmap) ;
paint.setColor(Color.GREEN);
paint.setTextSize(16); //設定字型大小
canvas.drawRect(10, 10, 50, 8, paint);
canvas.drawText("我沒有旋轉",50, 10, paint);
//儲存canvas之前的操作,在sava()和restore之間的操作不會對canvas之前的操作進行影響
canvas.save() ;
//順時針旋轉30度
canvas.rotate(30) ;
canvas.drawColor(Color.RED);
canvas.drawBitmap(iconbit, 20, 20, paint);
canvas.drawRect(50, 10, 80, 50, paint);
//canvas.translate(20,20);
canvas.drawText("我是旋轉的",115,20, paint);
//復原之前save()之前的屬性,並且將save()方法之後的roate(),translate()以及clipXXX()方法的操作清空
canvas.restore();
//平移(20,20)個畫素
//canvas.translate(20,20);
canvas.drawRect(80, 10, 110,30, paint);
canvas.drawText("我沒有旋轉",115,20, paint);
//將Bitmap物件轉換為Drawable影象資
//為ImageView設定影象
//imgSave.setImageBitmap(bitmap);
Drawable drawable = new BitmapDrawable(bitmap) ;
imgSave.setBackgroundDrawable(drawable) ;
}
}
總的來說,Canvas理解起來還是比較糾結的,尤其是它的幾個方法真是讓人頭疼, 希望你能夠自己編寫相應的程式碼
理解透徹,才真正的有所收穫。
相關推薦
Andriod中繪(畫)圖----Canvas的使用詳解
由於在網路上找到關於Canvas的使用都比較抽象,也許是我的邏輯思維不太好吧,總是感覺理解起來比較困難, 尤其是對save()和restore()方法的使用。本篇文章的內容就是對Canvas的使用進行一下總結,包括它的兩種不同的使用
eclipse中svn圖標詳解(轉)
tin note 引用 pda call use ips linked Opens - 已忽略版本控制的文件。可以通過Window → Preferences → Team → Ignored Resources.來忽略文件。A file ignored by versio
UML---用例圖中的Include和Extend詳解
前言: 在做UML相關題的時候,發現總是分不清Include和Extend之間的區別,特此釋出一篇部落格,來總結一下這兩個關係的不同,同時也分享給大家,讓了此篇部落格的同學們都不會再迷糊 Include: Include是指“包含的關係”,指多個用例中都包含一個
PlantUML畫類圖、流程圖、時序圖使用詳解
程式設計師難免要經常畫流程圖,狀態圖,時序圖等。以前經常用 visio 畫,經常為矩形畫多大,擺放在哪等問題費腦筋。有時候修改文字後,為了較好的顯示效果不得不再去修改圖形。今天介紹的工具是如何使用 PlantUML 的外掛畫流程圖,狀態圖,時序圖等。這是一種程式設計師看了就會愛上
html5 canvas中的屬性和方法詳解
建立一個Canvas畫布的方法如下 <canvas id=”canvas” width=”600” height=”400”></canvas> 可以在標籤中新增<canvas>標籤不可用時的替代文字,如下所示: <canv
android canvas layer (圖層)詳解與進階
1 概述 前面的canvas變換文章中,已經粗略的講解過saveLayer的知識,只是圖層的概念沒有詳細的講解。這裡將詳細講解layer。在使用相關方法和flag的時候,先關閉硬體加速。如果需要開啟,參照谷歌官方的硬體加速表格。硬體加速版本 2 save
Javascript中的apply與call詳解
選項 this 模式 div sun fun object 面向 傳遞 JavaScript中有一個call和apply方法,其作用基本相同,但也有略微的區別。 一、方法定義 1、call 方法 語法:call([thisObj[,arg1[, arg2[
JQuery中$.ajax()方法參數詳解(轉載)
瀏覽器 object 服務器 字符串 false type: 要求為String類型的參數,請求方式(post或get)默認為get。註意其他http請求方法,例如put和 delete也可以使用,但僅部分瀏覽器支持。timeout: 要求為Number類型的參數,設置請求超時時
JavaScript中數組對象詳解
稀疏數組 nsh isa 學習過程 bnf value 明顯 global sci Array對象即數組對象用於在單個變量中存儲多個值,JS的數組是弱類型的,所以允許數組中含有不同類型的元素,數組元素甚至可以是對象或者其他數組。 創建數組的語法 1、Array構造器 1
react native 中textInput的value屬性詳解
hold eric 工作 als size 保持 chang 無奈 bsp TextInput用法就不多講了,主要記錄下遇到的一個怪問題。 背景:項目需要開發一個充值頁面,需要一個輸入框,然後幾個按鈕,輸入框是允許用戶自己輸入任意金額,按鈕是可以讓用戶快捷選擇金
TP5中關聯模型的使用詳解
php 關聯模型 tp5 首先是model裏,舉個例子,user.php<?phpnamespace app\rbac\model;use think\Model;class User extends Model{ public function roleusers() {
Android Studio中Git和GitHub使用詳解
可能 必須 窗口 gin 擁有 說明 詳細 對話 發現 一、Git和GitHub簡述 1.Git 分布式版本控制系統,最先使用於Linux社區,是一個開源免費的版本控制系統,功能類似於SVN和CVS。Git與其他版本管理工具最大的區別點和優點就是分布式;
Django中的request對象詳解
當前 perm 請求 詳細 spa ati 用戶輸入 刪除 完整路徑 URLconf文件匹配到用戶輸入的路徑後,會調用對應的view函數,並將 HttpRequest對象 作為第一個參數傳入該函數。 下面說說HttpRequest對象: 他其實是一個實例對象,屬性有:
css中偽類/偽元素詳解
input 其他 中文 tro 網頁 單元 web link 語言 一、偽類和偽元素 偽類和偽元素都是用來修飾不在文檔樹中的部分,區別在於, 偽類用於當已有元素處於的某個狀態時,為其添加對應的樣式,這個狀態是根據用戶行為而動態變化的(如:hover/:active)。
Java中的異常和處理詳解
stat 一個 局部變量 lose 出了 object sta tof .html 原文出處:代碼鋼琴家 簡介 程序運行時,發生的不被期望的事件,它阻止了程序按照程序員的預期正常執行,這就是異常。異常發生時,是任程序自生自滅,立刻退出終止,還是輸出錯誤給用戶?或者用C語
Swift 中的Closures(閉包)詳解
mount light sca ring 需要 line rem sin 代碼 Swift 中的Closures(閉包)詳解 在Swift沒有發布之前,所有人使用OC語言編寫Cocoa上的程序,而其中經常被人們討論的其中之一 -- Block 一直備受大家的喜愛。在Swif
Spring中的applicationContext文件詳解
finance 初始化 tgui 解析 示例 row -m 所有 table <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/sche
JQuery中$.ajax()方法參數詳解
返回 自動轉換 time err last 需要 可選 修改 方式 url: 要求為String類型的參數,(默認為當前頁地址)發送請求的地址。 type: 要求為String類型的參數,請求方式(post或get)默認為get。註意其他http請求方法,例如put和
C#中的IDisposable模式用法詳解
數據庫 nor 是否 entry block 記錄日誌 自定義 技術分享 ssa 本文實例講述了C#中IDisposable模式的用法,針對垃圾資源的回收進行了較為詳細的講解。分享給大家供大家參考之用。具體方法如下: 首先,對於垃圾回收而言,在C#中,托管資源的垃圾回收是
vue2.0 中#$emit,$on的使用詳解
額外 return turn isp div 傳遞 call sele 發的 vue1.0中 vm.$dispatch 和 vm.$broadcast 被棄用,改用$emit,$on 1. vm.$on( event, callback ) 監聽當前實例上的自定義事件。