1.定义

SurfaceView继承自View,内嵌了一个专门用于绘制的Surface,Surfaceview不仅可以控制这个Surface的格式和尺寸,还能控制其绘制位置;因为可以直接从内存或者DMA等硬件接口取得图像数据,所以是个非常重要的绘图容器。

2.使用

首先要知道SurfaceView的一些特性,然后根据特性决定用途;

* SurfaceView 单位时间内完成界面的大量多次更新

* 双缓冲机制 :

* A线程----更新ui -----后台计算---更新ui

* B线程----后台计算----更新ui ---后台计算

* 可以在子线程更新ui

在主线程之外的线程中向屏幕绘图上,这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。

surfaceView.getHolder().addCallback(new Callback() {

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //surfaceView被销毁时调用
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //surfaceView被创建时调用
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        //surfaceView发生变化时调用
    }
});

首先继承SurfaceView并实现SurfaceHolder.Callback接口
使用接口的原因:因为使用SurfaceView 有一个原则,所有的绘图工作必须得在Surface 被创建之后才能开始(。基本上我们可以把它当作显存的一个映射,写入到Surface 的内容可以被直接复制到显存从而显示出来,这使得显示速度会非常快),而在Surface 被销毁之前必须结束。所以Callback 中的surfaceCreated 和surfaceDestroyed 就成了绘图处理代码的边界。

3.实例

sv.getHolder().addCallback(new Callback() {

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    System.out.println("surface被销毁了");
                    flag = false;
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    System.out.println("surface创建了");
                    flag = true;
                    new Thread(){
                        public void run() {
                            for(int i = 0;i<100;i++){
                                if(!flag){
                                    return ;
                                }
                            //界面里面内容显示的控制器
                                SurfaceHolder holder = sv.getHolder();
                                Canvas  canvas = holder.lockCanvas();
                                canvas.drawColor(Color.BLACK);
                                int radius = 5+i;
                                Paint paint = new Paint();
                                paint.setColor(Color.RED);
                                canvas.drawCircle(250, 250, radius, paint);
                                holder.unlockCanvasAndPost(canvas);
                                SystemClock.sleep(100);
                            }
                        };
                    }.start();
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width,
                        int height) {
                    System.out.println("surface大小发生了变化");
                }
            });

   上述代码实现的内容是canvas动态地画一个半径逐渐增大的圆形成的动画;

   整个过程:继承SurfaceView并实现SurfaceHolder.Callback接口 ----> SurfaceView.getHolder()获得SurfaceHolder对象 ---->SurfaceHolder.addCallback(callback)添加回调函数----   >SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布----> Canvas绘画 ---->SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。

 

   下面贴出SurfaceView实现视频播放器的实例:

    

sv = (SurfaceView) findViewById(R.id.sv);
            sp = getSharedPreferences("config", MODE_PRIVATE);

            sv.getHolder().addCallback(new Callback() {

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    System.out.println("surface被销毁");
                    if(mediaPlayer!=null){
                        int position = mediaPlayer.getCurrentPosition();
                        Editor editor  = sp.edit();
                        editor.putInt("position", position);
                        editor.commit();
                        mediaPlayer.stop();
                        mediaPlayer.release();
                    }
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    System.out.println("surface被创建");
                    try {
                        mediaPlayer = new MediaPlayer();
                        mediaPlayer.setDataSource("/mnt/sdcard/oppo.3gp");
                        mediaPlayer.prepare();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //指定多媒体的内容实在holder里面显示
                    mediaPlayer.setDisplay(holder);
                    mediaPlayer.start();
                    mediaPlayer.seekTo(sp.getInt("position", 0));
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width,
                        int height) {
                }
            });

4.小结

   SurfaceView的使用远不止于此,它比想象的更加强大,后面会涉及到SurfaceView的进阶使用.