关闭

Android SurfaceView的使用

标签: SurfaceVie
1306人阅读 评论(0) 收藏 举报
分类:

概述

定义

SurfaceView是View类的继承类,这个View里内嵌了一个专门用于绘制的Surface,这个可以类似的理解成为一个在View里的Canvas(实际上Surface中包含一个Canvas)。你可以控制这个Surface的格式和尺寸。Surfaceview类则控制这个Surface在屏幕上的正确位置。
SurfaceView使用的方式与任何View所派生的类都是完全相同的。可以像其他View那样应用动画,并把它们放到布局中。

你可以通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口。
surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁。这样能节省资源。如果你要查看 surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。
surfaceview的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:

  • 所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。
  • 由于surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface。

特性

在一般情况下,应用程序的View都是在UI线程中绘制的。UI线程同时也用来处理所有的用户交互(例如按钮单击或者文本输入)。
当需要快速地更新View的UI,或者当前渲染代码阻塞UI线程的时间过长的时候,SurfaceView就是解决上述问题的最佳选择。SurfaceView封装了一个Surface对象,而不是Canvas。这一点很重要,因为Surface可以使用后台线程绘制。对于那些资源敏感的操作,或者那些要求快速更新或者高速帧率的地方,例如使用3D图形,创建游戏,或者实时预览摄像头,这一点特别有用。

根据游戏特点,一般分成两类。

  • 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。
  • 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

实现

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

需要重写的方法:

//在surface的大小发生改变时激发
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){}  
//在创建时激发,一般在这里调用画图的线程
public void surfaceCreated(SurfaceHolder holder){} 
//销毁时激发,一般在这里将画图的线程停止、释放
public void surfaceDestroyed(SurfaceHolder holder) {} 

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

关于SurfaceHolder:
这里用到了一个类SurfaceHolder,可以把它当成surface的控制器,用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。
SurfaceView里面有个getHolder方法,我们可以获取一个SurfaceHolder。通过SurfaceHolder可以监听SurfaceView的生命周期以及获取Canvas对象。
几个需要注意的方法:

// 给SurfaceView当前的持有者一个回调对象
abstract void addCallback(SurfaceHolder.Callback callback);
// 锁定画布,一般在锁定后就可以通过其返回画布对象Canvas,在其上面画图等操作了
abstract Canvas lockCanvas();
// 锁定画布的某个区域进行画图,相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度
abstract Canvas lockCanvas(Rect dirty);
// 结束锁定画图,并提交改变
abstract void unlockCanvasAndPost(Canvas canvas);

使用

代码如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }

    //视图内部类
    class MyView extends SurfaceView implements SurfaceHolder.Callback
    {
        private SurfaceHolder holder;
        private MyThread myThread;
        public MyView(Context context) {
            super(context);
            holder = this.getHolder();
            holder.addCallback(this);
            myThread = new MyThread(holder);//创建一个绘图线程
        }

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

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            myThread.isRun = true;
            myThread.start();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            myThread.isRun = false;
        }

    }
    //线程内部类
    class MyThread extends Thread {
        private SurfaceHolder holder;
        public boolean isRun ;
        public  MyThread(SurfaceHolder holder) {
            this.holder =holder;
            isRun = true;
        }
        @Override
        public void run()
        {
            int count = 0;
            while(isRun) {
                Canvas c = null;
                try {
                    synchronized (holder) {
                        c = holder.lockCanvas();//锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
                        c.drawColor(Color.BLACK);//设置画布背景颜色
                        Paint p = new Paint(); //创建画笔
                        p.setColor(Color.WHITE);
                        p.setTextSize(100);
                        Rect r = new Rect(100, 50, 1000, 250);
                        c.drawRect(r, p);
                        c.drawText("这是第"+(count++)+"秒", 300, 400, p);
                        Thread.sleep(1000);//睡眠时间为1秒
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if(c!= null) {
                        holder.unlockCanvasAndPost(c);//结束锁定画图,并提交改变。
                    }
                }
            }
        }
    }
}

运行程序,效果图如下:
这里写图片描述

0
0
查看评论

Android视图SurfaceView的使用

Android视图SurfaceView的使用 绘制圆形进度条。
  • hehe26
  • hehe26
  • 2016-10-31 12:01
  • 2161

Android视图SurfaceView的实现原理分析

在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,...
  • Luoshengyang
  • Luoshengyang
  • 2013-03-16 16:57
  • 201060

android的surfaceview的用法

参考了文章:Android中SurfaceView的使用详解,  但在该文基础上进行了一定的修改。       说到sufaceview就得讲讲这个类是干什么的。是的,它是用来控制自定义绘图的。起码我现在看到的用法都是这样。     &...
  • heikefangxian23
  • heikefangxian23
  • 2015-11-30 11:36
  • 19523

Android中SurfaceView使用详解

1.什么是SurfaceView?     Surface意为表层、表面,顾名思义SurfaceView就是指一个在表层的View对象。为什么说是在表层呢,这是因为它有点特殊跟其他View不一样,其他View是绘制在“表层”的上面,而它就是充当“表层”本身。SDK的文档 说到:...
  • android_cmos
  • android_cmos
  • 2017-04-03 12:54
  • 1987

AndroidN SurfaceView新特性

之前的博文SurfaceView 基础用法对SurfaceView做了基础的介绍,但没有对其不足的地方进行说明,本篇讲SurfaceView的不足之处,已及AndroidN上SurfaceView的新特性。
  • azhengye
  • azhengye
  • 2016-08-26 08:15
  • 1533

Android实时取景:用SurfaceView实现 -- Camera 二

实现与上文一样的结果 直接贴源码 package com.example.administrator.camerasurfaceview; import android.app.Activity; import android.graphics.PixelFormat; import an...
  • JKjiang123
  • JKjiang123
  • 2017-12-11 15:02
  • 444

Android SurfaceView的绘制详解

在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,...
  • aa841538513
  • aa841538513
  • 2016-08-23 11:51
  • 6730

Android--SurfaceView使用详解

SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置。         surfac...
  • chaoyu168
  • chaoyu168
  • 2016-05-17 14:17
  • 6657

Android转载之SurfaceView使用详解

SurfaceView是视图(View)的继承类,这个视图里内嵌了一个专门用于绘制的Surface。你可以控制这个Surface的格式和尺寸。Surfaceview控制这个Surface的绘制位置。         surf...
  • Lingbulei
  • Lingbulei
  • 2017-11-18 21:14
  • 249

Android中的Surface和SurfaceView之我见

一、什么是Surface            简单的说Surface对应了一块屏幕缓冲区,每个window对应一个Surface,任何View都要画在Surface的Canvas上(后面有原因解释...
  • tgww88
  • tgww88
  • 2012-09-13 11:33
  • 4450
    个人资料
    • 访问:213284次
    • 积分:2757
    • 等级:
    • 排名:第15475名
    • 原创:100篇
    • 转载:11篇
    • 译文:0篇
    • 评论:43条
    最新评论