SurfaceView的基本使用

  • Post author:
  • Post category:其他




SurfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器,这次我就用两篇文章来介绍SurfaceView的用法。网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,我这里就直接在普通的用户界面调用SurfaceHolder的lockCanvas和unlockCanvasAndPost。



先来看看程序运行的截图:












截图1主要演示了直接把正弦波绘画在SurfaceView上












对比上面的左右两图,右图用.lockCanvas(null),而左图用.lockCanvas(new Rect(oldX, 0, oldX + length,


getWindowManager().getDefaultDisplay().getHeight())),对比一下两个效果,由于左图是按指定Rect绘画,所以效率会比右图的全控件绘画高些,并且在清屏之后(canvas.drawColor(Color.BLACK))不会留有上次绘画的残留。




接下来贴出main.xml的源码:



  1. <linearlayout xmlns:android=”http://schemas.android.com/apk/res/android”

  2. android:layout_width=”fill_parent” android:layout_height=”fill_parent”

  3. android:orientation=”vertical”>


  4. <linearlayout android:id=”@+id/LinearLayout01″

  5. android:layout_width=”wrap_content” android:layout_height=”wrap_content”>

  6. <button android:id=”@+id/Button01″ android:layout_width=”wrap_content”

  7. android:layout_height=”wrap_content” android:text=”简单绘画”>

  8. <button android:id=”@+id/Button02″ android:layout_width=”wrap_content”

  9. android:layout_height=”wrap_content” android:text=”定时器绘画”>


  10. <surfaceview android:id=”@+id/SurfaceView01″

  11. android:layout_width=”fill_parent” android:layout_height=”fill_parent”>



复制代码



接下来贴出程序源码:





  1. package com.testSurfaceView;


  2. import java.util.Timer;

  3. import java.util.TimerTask;


  4. import android.app.Activity;

  5. import android.graphics.Canvas;

  6. import android.graphics.Color;

  7. import android.graphics.Paint;

  8. import android.graphics.Rect;

  9. import android.os.Bundle;

  10. import android.util.Log;

  11. import android.view.SurfaceHolder;

  12. import android.view.SurfaceView;

  13. import android.view.View;

  14. import android.widget.Button;


  15. public class testSurfaceView extends Activity {


  16. /** Called when the activity is first created. */

  17. Button btnSimpleDraw, btnTimerDraw;

  18. SurfaceView sfv;

  19. SurfaceHolder sfh;


  20. private Timer mTimer;

  21. private MyTimerTask mTimerTask;

  22. int Y_axis[],//保存正弦波的Y轴上的点

  23. centerY,//中心线

  24. oldX,oldY,//上一个XY点

  25. currentX;//当前绘制到的X轴上的点


  26. @Override

  27. public void onCreate(Bundle savedInstanceState) {


  28. super.onCreate(savedInstanceState);

  29. setContentView(R.layout.main);


  30. btnSimpleDraw = (Button) this.findViewById(R.id.Button01);

  31. btnTimerDraw = (Button) this.findViewById(R.id.Button02);

  32. btnSimpleDraw.setOnClickListener(new ClickEvent());

  33. btnTimerDraw.setOnClickListener(new ClickEvent());

  34. sfv = (SurfaceView) this.findViewById(R.id.SurfaceView01);

  35. sfh = sfv.getHolder();


  36. //动态绘制正弦波的定时器

  37. mTimer = new Timer();

  38. mTimerTask = new MyTimerTask();


  39. // 初始化y轴数据

  40. centerY = (getWindowManager().getDefaultDisplay().getHeight() – sfv

  41. .getTop()) / 2;

  42. Y_axis = new int[getWindowManager().getDefaultDisplay().getWidth()];

  43. for (int i = 1; i < Y_axis.length; i++) {// 计算正弦波

  44. Y_axis[i – 1] = centerY

  45. – (int) (100 * Math.sin(i * 2 * Math.PI / 180));

  46. }

  47. }


  48. class ClickEvent implements View.OnClickListener {



  49. @Override

  50. public void onClick(View v) {



  51. if (v == btnSimpleDraw) {


  52. SimpleDraw(Y_axis.length-1);//直接绘制正弦波


  53. } else if (v == btnTimerDraw) {


  54. oldY = centerY;

  55. mTimer.schedule(mTimerTask, 0, 5);//动态绘制正弦波

  56. }


  57. }


  58. }


  59. class MyTimerTask extends TimerTask {


  60. @Override

  61. public void run() {



  62. SimpleDraw(currentX);

  63. currentX++;//往前进

  64. if (currentX == Y_axis.length – 1) {//如果到了终点,则清屏重来

  65. ClearDraw();

  66. currentX = 0;

  67. oldY = centerY;

  68. }

  69. }


  70. }


  71. /*

  72. * 绘制指定区域

  73. */

  74. void SimpleDraw(int length) {


  75. if (length == 0)

  76. oldX = 0;

  77. Canvas canvas = sfh.lockCanvas(new Rect(oldX, 0, oldX + length,

  78. getWindowManager().getDefaultDisplay().getHeight()));// 关键:获取画布

  79. Log.i(“Canvas:”,

  80. String.valueOf(oldX) + “,” + String.valueOf(oldX + length));


  81. Paint mPaint = new Paint();

  82. mPaint.setColor(Color.GREEN);// 画笔为绿色

  83. mPaint.setStrokeWidth(2);// 设置画笔粗细


  84. int y;

  85. for (int i = oldX + 1; i < length; i++) {// 绘画正弦波

  86. y = Y_axis[i – 1];

  87. canvas.drawLine(oldX, oldY, i, y, mPaint);

  88. oldX = i;

  89. oldY = y;

  90. }

  91. sfh.unlockCanvasAndPost(canvas);// 解锁画布,提交画好的图像

  92. }


  93. void ClearDraw() {


  94. Canvas canvas = sfh.lockCanvas(null);

  95. canvas.drawColor(Color.BLACK);// 清除画布

  96. sfh.unlockCanvasAndPost(canvas);


  97. }

  98. }


复制代码