橘子味的心
标题:10.4 使用SurfaceView绘制静态图像

使用 SurfaceView 绘图需要为 SurfaceView 对象添加 SurfaceHoloder.Callback 接口,并在该接口的 surfaceCreated() 方法中通过 lockCanvas() 方法获取 Canvas 对象,以此保证当获取 Canvas 时,SurfaceView 对象可用。

当绘图工作完成后,通过 SurfaceHoloder.unlockCanvas-AndPost() 方法将绘制的图像显示出来,并释放 Canvas 对象。

实例 SurfaceViewDrawDemo 演示了使用 SurfaceView 组件绘制静态图像的过程,其绘制的内容与《Android使用Bitmap绘图实例》教程中绘制的内容完全相同。

通过该实例,我们可以清楚地认识到使用 SurfaceView 绘图与使用 View 绘图的不同之处,该实例运行效果如图 1 所示。

SurfaceView绘图效果
图 1  SurfaceView 绘图效果

实例 SurfaceViewDrawDemo 使用的布局文件 main.xml 内容如下:
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical">
  7.  
  8. <TextView
  9. android:layout_width="fill_parent"
  10. android:layout_height="wrap_content"
  11. android:text="@string/hello" />
  12.  
  13. <SurfaceView
  14. android:id="@+id/surfaceViewl"
  15. android:layout_width="fill_parent"
  16. android:layout_height="fill_parent" />
  17. </LinearLayout>
在 LinearLayout 布局中添加了一个 SurfaceView 组件,通过该组件进行绘图。

实例 SurfaceViewDrawDemo 的主 Activity 为 SurfaceDrawDemoActivity,其代码如下:
  1. import android.app.Activity;
  2. import android.graphics.Canvas;
  3. import android.graphics.Color;
  4. import android.graphics.Paint;
  5. import android.graphics.Path;
  6. import android.graphics.RectF;
  7. import android.os.Bundle;
  8. import android.view.SurfaceHolder;
  9. import android.view.SurfaceView;
  10.  
  11. public class SurfaceDrawDemoActivity extends Activity {
  12. private SurfaceView mySurfaceView;
  13. private float[] mPts;
  14. private static final float SIZE = 300;
  15. private static final int SEGS = 32;
  16. private static final int X = 0;
  17. private static final int Y = 1;
  18.  
  19. /**
  20. * Called when the activity is first created.
  21. */
  22. @Override
  23. public void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(R.layout.main);
  26. buildPoints();
  27. mySurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
  28. SurfaceHolder surfaceHolder = mySurfaceView.getHolder();
  29. SurfaceHolder.addCallback(new SurfaceHolder.Callback() {
  30.  
  31. @Override
  32. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  33. // TODO Auto-generated method stub
  34. }
  35.  
  36. @Override
  37. public void surfaceCreated(SurfaceHolder holder) {
  38. //必须在该方法中获取Canvas对象,才能保证SurfaceView可用
  39. Canvas canvas = holder.lockCanvas(); //获得canvas对象
  40. //使用Canvas绘图
  41. //画布移动到(10, 10)位置
  42. canvas.translate(10, 10);
  43. //画布使用白色填充
  44. canvas.drawColor(Color.WHITE);
  45. //创建红色画笔,使用单像素宽度,绘制直线
  46. Paint paint = new Paint();
  47. paint.setColor(Color.RED);
  48. paint.setStrokeWidth(0);
  49. canvas.drawLines(mPts, paint);
  50. //创建蓝色画笔,宽度为3,绘制相关点
  51. paint.setColor(Color.BLUE);
  52. paint.setStrokeWidth(3);
  53. canvas.drawPoints(mPts, paint);
  54. //创建Path,并沿着path显示文字信息
  55. RectF rect = new RectF(10, 250, 290, 480);
  56. Path path = new Path();
  57. path.addArc(rect, -180, 180);
  58. paint.setTextSize(18);
  59. paint.setColor(Color.BLUE);
  60. canvas.drawTextOnPath("在SurfaceView中使用Canvas对象绘制静态图实例", path, 0,
  61. 0, paint);
  62. holder.unlockCanvasAndPost(canvas); //释放canvas对象
  63. }
  64.  
  65. @Override
  66. public void surfaceDestroyed(SurfaceHolder holder) {
  67. // TODO Auto-generated method stub
  68. }
  69. });
  70. }
  71.  
  72. private void buildPoints() {
  73. //生成一系列点
  74. final int ptCount = (SEGS + 1) * 2;
  75. mPts = new float[ptCount * 2];
  76. float value = 0;
  77. final float delta = SIZE / SEGS;
  78. for (int i = 0; i <= SEGS; i++) {
  79. mPts[i * 4 + X] = SIZE - value;
  80. mPts[i * 4 + Y] = 0;
  81. mPts[i * 4 + X + 2] = 0;
  82. mPts[i * 4 + Y + 2] = value;
  83. value += delta;
  84. }
  85. }
  86. }