## 第十一天.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)