## 第十一天.Android圖形技術 ##
### 11.1 Paint類與Canvas類 ###
#### 11.1.1 繪圖Paint類 ####
```
Paint mPaint = new Paint();
/* 設置Paint為無鋸齒 */
mPaint.setAntiAlias(true);
/* 設置Paint的顏色 */
mPaint.setColor(Color.RED);
mPaint.setColor(Color.BLUE);
/* 同樣是設置顏色 */
mPaint.setColor(Color.rgb(255, 0, 0));
/* 提取顏色 */
Color.red(0xcccccc);
Color.green(0xcccccc);
/* 設置paint的顏色和Alpha值(a,r,g,b) */
mPaint.setARGB(255, 255, 0, 0);
/* 設置paint的Alpha值 */
mPaint.setAlpha(220);
/* 設置字體的尺寸 */
mPaint.setTextSize(14);
// 設置paint的風格為“空心”.
// 當然也可以設置為“實心”(Paint.Style.FILL)
mPaint.setStyle(Paint.Style.STROKE);
// 設置“空心”的外框的寬度。
mPaint.setStrokeWidth(5);
/* 得到Paint的一些屬性 */
Log.i(TAG, "paint的顏色:" + mPaint.getColor());
Log.i(TAG, "paint的Alpha:" + mPaint.getAlpha());
Log.i(TAG, "paint的外框的寬度:" +mPaint.getStrokeWidth());
Log.i(TAG, "paint的字體尺寸:" +mPaint.getTextSize());
/* 繪制一個矩形 */
canvas.drawRect((320 - 80) / 2, 20, (320- 80) / 2 + 80, 20 + 40, mPaint);
/* 設置風格為實心 */
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.GREEN);
/* 繪制綠色實心矩形 */
canvas.drawRect(0, 20, 40, 20 + 40,mPaint);
```
#### 11.1.2 在線程中更新界面 ####
```
public void run() {
while(!Thread.currentThread().isInterrupted())
{
try{
Thread.sleep(100);
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
}
//使用postInvalidate可以直接在線程中更新界面
postInvalidate();//會調用onDraw(Canvascanvas)方法
}
}
```
研究案例PaintDemo
#### 11.1.3 Canvas畫布類 ####
```
public void onDraw(Canvas canvas){
super.onDraw(canvas);
/*設置畫布的顏色 */
canvas.drawColor(Color.BLACK);
/*設置取消鋸齒效果 */
mPaint.setAntiAlias(true);
/*設置裁剪區域 */
canvas.clipRect(10,10, 280, 260);
/*線鎖定畫布 */
canvas.save();
/*旋轉畫布 */
canvas.rotate(45.0f);
/*設置顏色及繪制矩形 */
mPaint.setColor(Color.RED);
canvas.drawRect(newRect(15,15,140,70), mPaint);
/*解除畫布的鎖定 */
canvas.restore();
/*設置顏色及繪制另一個矩形 */
mPaint.setColor(Color.GREEN);
canvas.drawRect(newRect(150,75,260,120), mPaint);
}
```
研究案例PaintDemo2
### 11.2 SurfaceView類 ###
#### 11.2.1 SurfaceView類 ####
+ 執行效率高
+ 可以直接訪問畫布Canvas
+ 開發手機游戲經常用
#### 11.2.2 SurfaceView使用要點 ####
1. public class GameSurfaceView extendsSurfaceView implementsSurfaceHolder.Callback,Runnable
2. 定義SurfaceHolder對象:
```
SurfaceHoldermSurfaceHolder= this.getHolder();
```
3. 添加回調:
```
mSurfaceHolder.addCallback(this);
this.setFocusable(true);
```
4. 在回調方法surfaceCreated()中開啟繪圖線程。
5. 在繪圖線程中繪制圖形。
#### 11.2.3 SurfaceView回調方法 ####
```
// 在surface的大小發生改變時激發
publicvoid surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
//在surface創建時激發
publicvoid surfaceCreated(SurfaceHolder holder){
//開啟繪圖線程
newThread(this).start();
}
//在surface銷毀時激發
publicvoid surfaceDestroyed(SurfaceHolder holder){
//停止循環
mbLoop= false;
}
```
#### 11.2.3 繪圖線程 ####
```
// 繪圖循環
publicvoid run(){
while(mbLoop){
try{
Thread.sleep(200);
}
catch(Exception e){
}
synchronized(mSurfaceHolder ){
draw();
}
}
}
```
#### 11.2.4 繪圖方法 ####
```
public void draw() {
//鎖定畫布,得到canvas
Canvascanvas= mSurfaceHolder.lockCanvas();
if(mSurfaceHolder==null || canvas == null ){
return;
}
//繪圖
PaintmPaint = new Paint();
mPaint.setColor(Color.BLACK);
//繪制矩形--清屏作用
canvas.drawRect(0,0, 320, 480, mPaint);
mPaint.setColor(Color.BLUE);
//繪制矩形
canvas.drawCircle((320- 25) / 2, y, 50, mPaint);
//繪制后解鎖,繪制后必須解鎖才能顯示
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
```
研究完整案例GameSurfaceViewDemo
### 11.3 繪制幾何形狀 ###
#### 11.3.1 繪制幾何形狀 ####
```
/* 定義矩形對象 */
Rectrect1 = new Rect();
/*設置矩形大小 */
rect1.left= 5; rect1.top = 5; rect1.bottom = 25; rect1.right = 45;
mPaint.setColor(Color.BLUE);
/*繪制矩形 */
canvas.drawRect(rect1,mPaint);
/*繪制矩形 */
canvas.drawRect(50,5, 90, 25, mPaint);
/*繪制圓形(圓心x,圓心y,半徑r,p) */
canvas.drawCircle(40,70, 30, mPaint);
/*定義橢圓對象 */
RectFrectf1 = new RectF();
/*設置橢圓大小 */
rectf1.left= 80; rectf1.top = 30; rectf1.right = 120; rectf1.bottom = 70;
/*繪制橢圓 */
canvas.drawOval(rectf1,mPaint);
/* 繪制多邊形 */
Pathpath1 = new Path();
/*設置多邊形的點*/
path1.moveTo(150+5,80-50);
path1.lineTo(150+45,80-50);
path1.lineTo(150+30,120-50);
path1.lineTo(150+20,120-50);
/*使這些點構成封閉的多邊形 */
path1.close();
mPaint.setColor(Color.GRAY);
/*繪制這個多邊形 */
canvas.drawPath(path1,mPaint);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(3);
/*繪制直線 */
canvas.drawLine(5,110, 315, 110, mPaint);
```
研究完整案例PaintDemo3
#### 11.3.2 ShapeDrawable繪制幾何圖形 ####
```
/* 實例化ShapeDrawable對象并說明是繪制一個矩形 */
ShapeDrawable mShapeDrawable = new ShapeDrawable(new RectShape());
//得到畫筆paint對象并設置其顏色
mShapeDrawable.getPaint().setColor(Color.RED);
Rectbounds = new Rect(5, 250, 55, 280);
/*設置圖像顯示的區域 */
mShapeDrawable.setBounds(bounds);
mShapeDrawable.draw(canvas);/* 繪制圖像 */
/*實例化ShapeDrawable對象并說明是繪制一個橢圓 */
mShapeDrawable= new ShapeDrawable(new OvalShape());
//得到畫筆paint對象并設置其顏色
mShapeDrawable.getPaint().setColor(Color.GREEN);
/*設置圖像顯示的區域 */
mShapeDrawable.setBounds(70,250, 150, 280);
/*繪制圖像 */
mShapeDrawable.draw(canvas);
Path path1 = new Path();
/*設置多邊形的點*/
path1.moveTo(150+5,80+80-50);
path1.lineTo(150+45,80+80-50);
path1.lineTo(150+30,80+120-50);
path1.lineTo(150+20,80+120-50);
/*使這些點構成封閉的多邊形 */
path1.close();
//PathShape后面兩個參數分別是寬度和高度
mShapeDrawable= new ShapeDrawable(new PathShape(path1,150,150));
//得到畫筆paint對象并設置其顏色
mShapeDrawable.getPaint().setColor(Color.BLUE);
/*設置圖像顯示的區域 */
mShapeDrawable.setBounds(100,170, 200, 280);
/*繪制圖像 */
mShapeDrawable.draw(canvas);
```
研究案例PaintDemo3中GameView2.java
### 11.4 圖形繪制與旋轉縮放 ###
#### 11.4.1 繪制圖像1 ####
```
/*從資源文件中裝載圖片 */
//getResources()->得到Resources
//getDrawable()->得到資源中的Drawable對象,參數為資源索引ID
//getBitmap()->得到Bitmap
Bitmap mBitQQ = ((BitmapDrawable)getResources().getDrawable(R.drawable.qq)).getBitmap();
/*清屏效果 */
canvas.drawColor(Color.GRAY);
/*在屏幕(0,0)處繪制圖片mBitQQ */
GameView.drawImage(canvas,mBitQQ, 0, 0);
```
drawImage()參考后面
#### 11.4.2 繪制圖像2 ####
```
/**
* @param x屏幕上的x坐標
* @param y屏幕上的y坐標
* @param w要繪制的圖片的寬度
* @param h要繪制的圖片的高度
* @param bx圖片上的x坐標
* @param by圖片上的y坐標
*/
publicstatic void drawImage(Canvas canvas, Bitmap blt, int x,
int y, int w, int h,int bx, int by) {
Rectsrc = new Rect();// 圖片
Rectdst = new Rect();// 屏幕
src.left= bx; src.top = by; src.right = bx + w;
src.bottom= by + h;
dst.left= x; dst.top = y; dst.right = x + w;
dst.bottom= y + h;
canvas.drawBitmap(blt,src, dst, null);
src= null; dst = null;
}
```
#### 11.4.3 繪制圖像3 ####
```
/**
* 繪制一個Bitmap
* @param canvas 畫布
* @param bitmap 圖片
* @param x 屏幕上的x坐標
* @param y 屏幕上的y坐標
*/
public static void drawImage(Canvas canvas, Bitmap bitmap, int x, int y)
{
/*繪制圖像 */
canvas.drawBitmap(bitmap,x, y, null);
}
```
還需要使用線程更新界面
研究案例PaintDemo5
#### 11.4.5 圖像旋轉 ####
```
public void onDraw(Canvas canvas){
super.onDraw(canvas);
MatrixmMatrix = new Matrix();
/*重置mMatrix */
mMatrix.reset();
/*設置旋轉 */
mMatrix.setRotate(角度);
/*按mMatrix得旋轉構建新的Bitmap */
BitmapmBitQQ2 = Bitmap.createBitmap(mBitQQ, 0, 0, BitQQwidth,BitQQheight, mMatrix,true);
/*繪制旋轉之后的圖片 */
GameView.drawImage(canvas,mBitQQ2, (320-BitQQwidth)/2, 10);
mBitQQ2= null;
}
```
研究MatrixDemo
#### 11.4.6 圖像縮放 ####
```
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*重置mMatrix */
mMatrix.reset();
/*設置縮放 */
mMatrix.postScale(Scale,Scale);
/*按mMatrix得旋轉構建新的Bitmap */
BitmapmBitQQ2 = Bitmap.createBitmap(mBitQQ, 0, 0, BitQQwidth,BitQQheight, mMatrix,true);
/*繪制旋轉之后的圖片 */
GameView.drawImage(canvas,mBitQQ2, (320-BitQQwidth)/2, 10);
mBitQQ2= null;
}
```
研究MatrixScaleDemo
### 11.5 用Shader類進行渲染 ###
+ BitmapShader: Bitmap渲染
+ LinearGradient: 線性漸變渲染
+ ComposeShader: 混合渲染
+ RadialGradient: 環形漸變渲染
+ SweepGradient: 梯度渲染
研究案例ShaderDemo
[示例下載](http://www.apkbus.com/android-83479-1-1.html)