博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android SurfaceView详解
阅读量:5171 次
发布时间:2019-06-13

本文共 3988 字,大约阅读时间需要 13 分钟。

   SurfaceView继承了View,但是我们并不需要去实现它的draw方法来绘制自己,为什么呢?因为它和View有一个很大的区别,View在UI线程去更新自己;而SurfaceView则在一个子线程中去更新自己;这也显示出了它的优势,当制作游戏等需要不断刷新View时,因为是在子线程,避免了对UI线程的阻塞。

    SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。

        普通的Android控件,例如TextView、Button和CheckBox等,它们都是将自己的UI绘制在宿主窗口的绘图表面之上,这意味着它们的UI是在应用程序的主线程中进行绘制的。由于应用程序的主线程除了要绘制UI之外,还需要及时地响应用户输入,否则的话,系统就会认为应用程序没有响应了,因此就会弹出一个ANR对话框出来。对于一些游戏画面,或者摄像头预览、视频播放来说,它们的UI都比较复杂,而且要求能够进行高效的绘制,因此,它们的UI就不适合在应用程序的主线程中进行绘制。这时候就必须要给那些需要复杂而高效UI的视图生成一个独立的绘图表面,以及使用一个独立的线程来绘制这些视图的UI。

    只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了。

    SurfaceView里面有个getHolder方法,我们可以获取一个SurfaceHolder。通过SurfaceHolder可以监听SurfaceView的生命周期以及获取Canvas对象。Canvas相当于画布,你可以在上面画图,画线,画字以及其他图形。  

package com.example.shengchanglu.test;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;/** * Created by shengchanglu on 15/9/17. */public class MySurfaceView extends SurfaceView implements Callback, Runnable {    private Thread th;    private SurfaceHolder sfh;    private Canvas canvas;    private Paint paint;    private Bitmap bmp;    private int bmp_x, bmp_y;    private boolean himi;     public MySurfaceView(Context context, AttributeSet attrs) {        super(context);        this.setKeepScreenOn(true);        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.logo);        sfh = this.getHolder();        sfh.addCallback(this); //备注1        paint = new Paint();        paint.setAntiAlias(true);        this.setLongClickable(true);    }    public void surfaceCreated(SurfaceHolder holder) {
     int screenW = this.getWidth();     int screenH = this.getHeight();//surfaceView 在调用surfaceCreated前创建起来,在这里才能拿到长宽。而不是在上面的构造函数中 himi = true; th = new Thread(this, "himi_Thread_one");//备注2 th.start(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}    public void surfaceDestroyed(SurfaceHolder holder) {        himi = false;//备注3    }    public void draw() {        try {            canvas = sfh.lockCanvas();            if (canvas != null) {                canvas.drawColor(Color.WHITE);                canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);            }        } catch (Exception e) {        } finally {            if (canvas != null)                sfh.unlockCanvasAndPost(canvas);        }    }    public void run() {        while (himi) {//备注4            draw();            try {                Thread.sleep(100);            } catch (Exception ex) {            }        }    }}

 

/备注1

  SurfaceHolder.Callback接口:

  只要继承SurfaceView类并实现SurfaceHolder.Callback接口就可以实现一个自定义的SurfaceView了,SurfaceHolder.Callback在底层的Surface状态发生变化的时候通知View,SurfaceHolder.Callback具有如下的接口:

   surfaceCreated(SurfaceHolder holder):当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。

   surfaceChanged(SurfaceHolder holder, int format, int width,int height):当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。

  SurfaceHolder 类:

  它是一个用于控制surface的接口,它提供了控制surface 的大小,格式,上面的像素,即监视其改变的。 

 SurfaceView的getHolder()函数可以获取SurfaceHolder对象,Surface 就在SurfaceHolder对象内。虽然Surface保存了当前窗口的像素数据,但是在使用过程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或则Canvas lockCanvas()函数来获取                                                        Canvas对象,通过在Canvas上绘制内容来修改Surface中的数据。如果Surface不可编辑或则尚未创建调用该函数会返回null,在 unlockCanvas() 和 lockCanvas()中Surface的内容是不缓存的,所以需要完全重绘Surface的内容,为了提高效率只重绘变化的部分则可以调用   lockCanvas(Rect rect)函数来指定一个rect区域,这样该区域外的内容会缓存起来。在调用lockCanvas函数获取Canvas后,SurfaceView会获取Surface的一个同步锁直到调用unlockCanvasAndPost(Canvas canvas)函数才释放该锁,这里的同步机制保证在Surface绘制过程中                  不会被改变(被摧毁、修改)。

 

转载于:https://www.cnblogs.com/lsc183/p/4816485.html

你可能感兴趣的文章
小细节:Java中split()中的特殊分隔符 小数点
查看>>
【编程思想】【设计模式】【行为模式Behavioral】中介者模式Mediator
查看>>
后端接口时间戳或者随机数的作用
查看>>
tomcat docBase 和 path
查看>>
java默认语法、EL、JSTL表达式,JSTL和struts Tag标签的使用总结
查看>>
Vue笔记:使用 axios 发送请求
查看>>
富文本编辑器 - RichEditor
查看>>
java webcontroller访问时报415错误
查看>>
qcow2、raw、vmdk等镜像格式
查看>>
Jzoj5455【NOIP2017提高A组冲刺11.6】拆网线
查看>>
特定字符序列的判断(1028)
查看>>
华为面试
查看>>
平衡二叉树(AVL Tree)
查看>>
【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
查看>>
【CF799E】Aquarium decoration 线段树
查看>>
大运飞天 鲲鹏展翅
查看>>
从ECMA到W3C
查看>>
软件工程--第十六周学习进度
查看>>
yii2 ActiveRecord多表关联以及多表关联搜索的实现
查看>>
搜狗输入法安装--ubuntu
查看>>