android中SurfaceView的使用

SurfaceView

概念

SurfaceView的使用可以直接从内存或者DMA等硬件接口取得图像数据,是个非常重要的绘图容器。

它的特性:

可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重时造成主线程阻塞,从
而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等
等尽量在画布canvas中画出。
SurfaceView提供直接访问一个可画图的界面,可以控制在界面顶部的子视图层。
SurfaceView是提供给需要直接画像素而不是使用窗体不见的应用使用的。Android系统中一
个重要的概念和线索是Surface.View及其子类(TextView,Button等)要画在Surface上。每个
Surface创建一个Canvas对象(但属性时常改变),用来管理view在Surface上的绘图操作,如画
点画线,使用它是,一般都是出现在最顶层。

SurfaceView类 和View类的区别:

SurfaceView 和View的最本质的区别在于,surfaceView是在一个在新起的单独线程中可以重
新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面,可能会
引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞,那么将
无法响应按键,触摸等消息。当使用surfaceView由于是在新的线程中更新画面所以不会阻塞
你的UI主线程,但是这也会有另外一个问题,就是事件同步。比如你触屏了一下,你需要
surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这
样就会有点复杂了。
View:必须在UI的主线程中更新画面,用于被动更新画面。
surfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画
面。
所以在游戏的应用上,根据游戏的特点,一般分为两类:
a. 被动更新画面的。比如棋类,这种用view就好。因为画面的跟新依赖于onTouch来更新,
可以直接使用invalidate.因为这种情况下,这一次Touch和下一次Touch需要的时间比较长
些,不会产生
影响。
b.主动更新:比如一个人在一直跑动。这就需要一个单独的thread不停地重绘人的转台,避免
阻塞mian UI Thread 。所以显然view 不适合,需要surfaceView来控制。

实现方法

继承SurfaceView
实现SurfaceHolder.Callback接口并实现抽象方法

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

SurfaceHolder:

surface的控制器,用来操纵surface。处理它的Canvas上画的效果和动画,控制表面,大小,
像素等

几个需要注意的方法:

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

下面一个案例,小球从左上掉到右下角

这里写图片描述

MainActivity

public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {

    SurfaceView sv;
    SurfaceHolder holder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //使用控件
        sv = (SurfaceView) findViewById(R.id.sv);
        //获取控制器
        holder = sv.getHolder();
        //添加一个监听
        holder.addCallback(this);
    }

    @Override
    public void surfaceCreated(final SurfaceHolder holder) {
        //创建
        //只有在生命周期中,才能获取surfaceView的高度和宽度
        new Thread() {
            Paint paint = new Paint();

            @Override
            public void run() {
                paint.setColor(Color.RED);
                paint.setAntiAlias(true);
                paint.setDither(true);
                super.run();
                int index = 0;
                while (index++ < 100) {
                    int x = sv.getWidth() / 100 * index;
                    int y = sv.getHeight() / 100 * index;
                    //绘制
                    //锁住屏幕的一块矩阵,然后开始绘制
                    Canvas canvas = holder.lockCanvas();
                    //清屏
                    canvas.drawColor(Color.WHITE);
                    canvas.drawCircle(x, y, 20, paint);
                    //解锁并且复制到主界面
                    holder.unlockCanvasAndPost(canvas);
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        //大小修改, 横竖屏切换时
        //至少执行一次

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //销毁
    }


}

activity_main.xml;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.lesson12_surfaceview.MainActivity">

    <SurfaceView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值