打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
如何实现Android SurfaceView

SurfaceView是View的继承结构中一个比较特殊的子类,它的作用是提供一个第二线程来完成图形的绘制。因此应用程序不需要等待View的图形绘制,第二线程会异步完成图形的绘制。

SurfaceView实现的步骤:

  1. 继续SurfaceView并实现SurfaceHolder.Callback接口,该接口提供了SurfaceView创建、属性发生变化、销毁的时间点,那么你可以在适当的时间点完成具体的工作。
  2. 在SurfaceView初始化的时候调用SurfaceView.getHolder()方法获取一个SurfaceHolder,SurfaceHolder用于管理SurfaceView的工作过程。为了让SurfaceHolder起作用,必须为SurfaceHolder添加回调方法(即第一步实现的SurfaceHolder.Callback):
    Java代码
    1. SurfaceHolder.addCallBack(SurfaceHolder.Callback);  

  3. 在SurfaceView内创建第二线程的内部类(暂命名为SecondThread),它的主要任务是完成Canvas的图形绘制。为了能让SecondThread获得Canvas实例,必须给SecondThread传递在步骤二中获得的SurfaceHolder。现在就可以通过SurfaceHolder.lockCanvas()方法得到Canvas实例,并在Canvas上绘制图形。当图形绘制完成后,必须马上调用SurfaceHolder.unlockCanvasAndPost()为Canvas解锁,使其他线程可以使用该画布。

有几个注意点:

  1. 每一次通过SurfaceHolder获取的Canvas都会保持上一次绘制的状态。如果需要重新绘制图形,可以通过调用Canvas.drawColor()或Canvas.drawBitmap()来擦除上次遗留的图形。
  2. 并不一定只用第二线程来绘制图形,也可以开启第三,第四个线程来绘制图形。
  3. 注意线程安全。
  4. 不需要像View一样,调用invalidate()方法来指示图形的刷新。

SurfaceView的一个范例:
Java代码
  1. package com.sin90lzc.android.sample;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Collections;  
  5. import java.util.List;  
  6.   
  7. import android.content.Context;  
  8. import android.graphics.Canvas;  
  9. import android.graphics.Color;  
  10. import android.graphics.Paint;  
  11. import android.util.AttributeSet;  
  12. import android.util.Log;  
  13. import android.view.KeyEvent;  
  14. import android.view.SurfaceHolder;  
  15. import android.view.SurfaceView;  
  16.   
  17. public class CanvasView extends SurfaceView implements SurfaceHolder.Callback {  
  18.   
  19.     public static class Point {  
  20.         private float x;  
  21.         private float y;  
  22.   
  23.         public Point(float x, float y) {  
  24.             this.x = x;  
  25.             this.y = y;  
  26.         }  
  27.   
  28.         public float getX() {  
  29.             return x;  
  30.         }  
  31.   
  32.         public void setX(float x) {  
  33.             this.x = x;  
  34.         }  
  35.   
  36.         public float getY() {  
  37.             return y;  
  38.         }  
  39.   
  40.         public void setY(float y) {  
  41.             this.y = y;  
  42.         }  
  43.   
  44.         public Point nextPoint(Orien o) {  
  45.             float tempX = x;  
  46.             float tempY = y;  
  47.             switch (o) {  
  48.             case UP:  
  49.                 tempY = y - LINE_LENGTH;  
  50.                 break;  
  51.             case DOWN:  
  52.                 tempY = y + LINE_LENGTH;  
  53.                 break;  
  54.             case LEFT:  
  55.                 tempX = x - LINE_LENGTH;  
  56.                 break;  
  57.             case RIGHT:  
  58.                 tempX = x + LINE_LENGTH;  
  59.                 break;  
  60.             case UNKNOWN:  
  61.                 break;  
  62.             }  
  63.             return new Point(tempX, tempY);  
  64.         }  
  65.     }  
  66.   
  67.     enum Orien {  
  68.         UP, LEFT, DOWN, RIGHT, UNKNOWN  
  69.     }  
  70.   
  71.     public static class DrawThread extends Thread {  
  72.   
  73.         private List<Point> points = Collections  
  74.                 .synchronizedList(new ArrayList<Point>());  
  75.         private boolean mRun;  
  76.   
  77.         private Paint mPaint;  
  78.         private Orien curOrien;  
  79.   
  80.         public synchronized void setRun(boolean run) {  
  81.             this.mRun = run;  
  82.             notifyAll();  
  83.         }  
  84.   
  85.         public synchronized boolean getRun() {  
  86.             while (!mRun) {  
  87.                 try {  
  88.                     wait();  
  89.                 } catch (InterruptedException e) {  
  90.                     e.printStackTrace();  
  91.                 }  
  92.             }  
  93.             return mRun;  
  94.         }  
  95.   
  96.         //当按上下左右键时,生成相应的点坐标  
  97.         private synchronized boolean doKeyDown(int KeyCode, KeyEvent event) {  
  98.             synchronized (holder) {  
  99.                 Point p = null;  
  100.                 switch (KeyCode) {  
  101.                 case KeyEvent.KEYCODE_DPAD_UP:  
  102.                     if (curOrien != Orien.DOWN) {  
  103.                         curOrien = Orien.UP;  
  104.                         p = curPoint.nextPoint(curOrien);  
  105.                     }  
  106.                     break;  
  107.                 case KeyEvent.KEYCODE_DPAD_DOWN:  
  108.                     if (curOrien != Orien.UP) {  
  109.                         curOrien = Orien.DOWN;  
  110.                         p = curPoint.nextPoint(curOrien);  
  111.                     }  
  112.                     break;  
  113.                 case KeyEvent.KEYCODE_DPAD_LEFT:  
  114.                     if (curOrien != Orien.RIGHT) {  
  115.                         curOrien = Orien.LEFT;  
  116.                         p = curPoint.nextPoint(curOrien);  
  117.                     }  
  118.                     break;  
  119.                 case KeyEvent.KEYCODE_DPAD_RIGHT:  
  120.                     if (curOrien != Orien.LEFT) {  
  121.                         curOrien = Orien.RIGHT;  
  122.                         p = curPoint.nextPoint(curOrien);  
  123.                     }  
  124.                     break;  
  125.                 default:  
  126.                     curOrien = Orien.UNKNOWN;  
  127.                 }  
  128.                 if (p != null) {  
  129.                     curPoint = p;  
  130.                     points.add(p);  
  131.                     setRun(true);  
  132.                 }  
  133.                 Log.i(LOG_TAG, curOrien.toString());  
  134.             }  
  135.             return true;  
  136.         }  
  137.   
  138.         //当释放按键时,停止绘图  
  139.         private synchronized boolean doKeyUp(int KeyCode, KeyEvent event) {  
  140.             synchronized (holder) {  
  141.                 setRun(false);  
  142.                 curOrien = Orien.UNKNOWN;  
  143.             }  
  144.             return true;  
  145.         }  
  146.   
  147.         SurfaceHolder holder;  
  148.         private Point curPoint;  
  149.   
  150.         public DrawThread(SurfaceHolder holder) {  
  151.             this.holder = holder;  
  152.             mPaint = new Paint();  
  153.             mPaint.setColor(Color.GREEN);  
  154.             curPoint = new Point(5050);  
  155.             points.add(curPoint);  
  156.         }  
  157.   
  158.         public void resetPoint() {  
  159.         }  
  160.   
  161.         private void doDraw(Canvas canvas) {  
  162.             for (int i = 0; i + 1 < points.size(); i += 1) {  
  163.                 Point lp = points.get(i);  
  164.                 Point np = points.get(i + 1);  
  165.                 canvas.drawLine(lp.getX(), lp.getY(), np.getX(), np.getY(),  
  166.                         mPaint);  
  167.             }  
  168.         }  
  169.   
  170.         @Override  
  171.         public void run() {  
  172.             Canvas canvas = null;  
  173.             while (getRun()) {  
  174.                 try {  
  175.                     canvas = holder.lockCanvas();  
  176.                     synchronized (holder) {  
  177.                         doDraw(canvas);  
  178.                     }  
  179.                 } finally {  
  180.                     holder.unlockCanvasAndPost(canvas);  
  181.                     setRun(false);  
  182.                 }  
  183.             }  
  184.         }  
  185.     }  
  186.   
  187.     private DrawThread thread;  
  188.     public static final String LOG_TAG = "CanvasView";  
  189.     private static final int LINE_LENGTH = 30;  
  190.   
  191.     public CanvasView(Context context) {  
  192.         super(context);  
  193.   
  194.     }  
  195.   
  196.     public CanvasView(Context context, AttributeSet attrs) {  
  197.         super(context, attrs);  
  198.           
  199.         //SurfaceView由SurfaceHolder管理  
  200.         SurfaceHolder holder = getHolder();  
  201.         holder.addCallback(this);  
  202.         thread = new DrawThread(holder);  
  203.         thread.start();  
  204.     }  
  205.   
  206.     @Override  
  207.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  208.         return thread.doKeyDown(keyCode, event);  
  209.     }  
  210.   
  211.     @Override  
  212.     public boolean onKeyUp(int keyCode, KeyEvent event) {  
  213.         return thread.doKeyUp(keyCode, event);  
  214.     }  
  215.   
  216.     @Override  
  217.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  218.             int height) {  
  219.         Log.i(LOG_TAG, "surfaceChanged");  
  220.         thread.resetPoint();  
  221.         thread.setRun(true);  
  222.     }  
  223.   
  224.     @Override  
  225.     public void surfaceCreated(SurfaceHolder holder) {  
  226.         Log.i(LOG_TAG, "surfaceCreated");  
  227.         thread.resetPoint();  
  228.         thread.setRun(true);  
  229.     }  
  230.   
  231.     @Override  
  232.     public void surfaceDestroyed(SurfaceHolder holder) {  
  233.         Log.i(LOG_TAG, "surfaceDestroyed");  
  234.         thread.setRun(false);  
  235.     }  
  236.   
  237. }  
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
关于openGL, openGL ES, openVG及android中2D调用关系的报告
Surface、SurfaceView、SurfaceHolder及SurfaceHold...
Android Graphic : apk and Skia/OpenGL|ES - 一醉...
Android游戏框架SurfaceView介绍(附代码)
Android游戏开发----动画SurfaceView详解
Android中的Surface和SurfaceView
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服