Android中SurfaceView的使用

SurfaceView是简单高效的用于渲染图形的类,适合用于简单的2D游戏开发。

本文介绍了Android中SurfaceView的使用,包括使用SurfaceView绘制单个图形,多个图形,组合图形,并使组合图形移动。

详细代码:github.com/Baolvlv/LearnAndroid/tree/master/SurfaceView

        surfaceView主要用于游戏开发,当view需要频繁绘制时,会消耗很多资源,这时可以使用surfaceview进行。同时surfaceviwe可以在主线程之外的线程中进行。当画面需要被动更新时(靠事件触发,例如棋牌类游戏),可以使用view,而需要主动更新时,则选择surfaceview

1.SurfaceView的使用

创建一个类继承自SurfaceViwe,并实现SurfaceHolder.Callback接口,实现构造函数与借口的三个方法

publicMyView(Context context) {

super(context);

//添加回调函数

getHolder().addCallback(this);

}

//surface创建时执行

@Override

public voidsurfaceCreated(SurfaceHolder holder) {

}

//surface改变时执行

@Override

public voidsurfaceChanged(SurfaceHolder holder, intformat, intwidth, intheight) {

}

//surface意外销毁时执行

@Override

public voidsurfaceDestroyed(SurfaceHolder holder) {

}

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

getHolder().unlockCanvasAndPost(canvas);

2.SurfaceView绘制单个图形

声明化画笔,在构造方法中初始化并设置画笔颜色

//声明画笔

privatePaintpaint=null;

paint=newPaint();

paint.setColor(Color.RED);

在自定义的Draw方法中,设置画布颜色并绘制图形

public voiddraw(){

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

//设置画布颜色

canvas.drawColor(Color.WHITE);

//绘制长100宽100的矩形

canvas.drawRect(0,0,100,100,paint);

getHolder().unlockCanvasAndPost(canvas);

}

在surfaceCreate方法中调用绘制方法

public voidsurfaceCreated(SurfaceHolder holder) {

draw();

}

在MainActivity的onCreate方法中添加View

setContentView(newMyView(this));

3.SurfaceView绘制多个图形

直接调用canvas不断绘制即可绘制多个图形

当需要对其中的一个图形进行旋转,剪切等变换时,canvas.save与canvas.restore配合使用,用以不影响其他图形,旋转是通过旋转画布实现

canvas.save();

canvas.rotate(90,getWidth()/2,getHeight()/2);

canvas.drawLine(0,getHeight()/2,getWidth(),getHeight(),paint);

//还原画布

canvas.restore();

4.SurfaceView绘制组合图形

绘制组合图形有三个要点:

1.需要一个抽象的容器类,其子类为各种具体的图形,同时包含List储存各种子类图形

2.画布在主SurfaceView中设置好后,在逐级容器间传递

3.每个类得到画布后,绘制自己的图形

步骤:

自定义Container类,设置用于储存的List并在构造函数中初始化

public classContanier {

//储存子容器的List

privateListchildren=null;

//构造函数,实例化list

publicContanier(){

children=newArrayList();

}

编写向list中添加与删除view方法

//添加子view方法

public voidaddChildernView(Contanier child){

children.add(child);

}

//移除子view方法

public voidremoveChidernView(Contanier child){

children.remove(child);

}

编写向子容器传递画布并绘制其独特图形的方法,之后在子容器中进行复写

//向子容器传递画布并且子容器完成自己的绘制

public voidchildernViewCanvasAndDraw(Canvas canvas){

}

编写向逐级子容器传递画布的方法

//将画布传递给子容器,同时为容器内list中所有的子容器设置画布

public voidsetCanvas(Canvas canvas){

childernViewCanvasAndDraw(canvas);

for(Contanier c :children){

c.setCanvas(canvas);

}

编写具体图形类,继承自Contanier,作为容器可嵌套,构造函数初始化画笔

public classRectextendsContanier{

privatePaintpaint=null;

//构造函数初始化画笔

publicRect(){

paint=newPaint();

paint.setColor(Color.RED);

}

重写父类方法,接收画布绘制图形

public voidchildernViewCanvasAndDraw(Canvas canvas){

super.childernViewCanvasAndDraw(canvas);

canvas.drawRect(0,0,100,100,paint);

}

主surfaceView构造函数中实例化contanier及具体图形

privateContaniercontanier;

privateRectrect;

privateCirclecircle;

contanier=newContanier();

rect=newRect();

circle=newCircle();

rect.addChildernView(circle);

contanier.addChildernView(rect);

设置画布,并调用contanier类的方法传递画布

//创建画布,图形开始时锁定画布,图形结束后解锁画布

Canvas canvas = getHolder().lockCanvas();

//设置画布颜色

canvas.drawColor(Color.WHITE);

//为所有容器统一设置画布

contanier.setCanvas(canvas);

getHolder().unlockCanvasAndPost(canvas);

5.使组合图形移动

通过x,y坐标完成移动,首先设置x,y坐标变量

//设置坐标

private floatx=0,y=0;

get和set方法

//get和set方法

public voidsetX(floatx) {

this.x= x;

}

public floatgetX() {

returnx;

}

public voidsetY(floaty) {

this.y= y;

}

public floatgetY() {

returny;

}

在contanier类中为子容器逐级设置画布的方法中进行移动

在canvas的save与restore方法中,进行画布移动

/通过save和restore进行移动变化

canvas.save();

//根据当前的x,y坐标移动画布

canvas.translate(getX(),getY());

childernViewCanvasAndDraw(canvas);

for(Contanier c :children){

c.setCanvas(canvas);

}

canvas.restore();

在最外层的矩形子类中,绘制图形后,当前纵坐标增加1,作为下一次绘制时的纵坐标,实现不断移动

//不断增加画布移动坐标

this.setY(getY() +1);

在主surfaceView中,设置timer与timerTask,进行不断绘制

//创建计时器与计时器任务对象

privateTimertimer=null;

privateTimerTasktask=null;

//开始计时器方法

public voidstartTimer(){

timer=newTimer();

task=newTimerTask() {

//实例化timertask,复写run方法,不断进行绘制

@Override

public voidrun() {

draw();

}

};

//timer执行timerTask,100毫米后开始,每100毫秒执行一次

timer.schedule(task,100,100);

}

//停止计时器

public voidstopTimer(){

//当计时器不为空时,取消计时器,并设置为空

if(timer!=null){

timer.cancel();

timer=null;

}

在surfaceCreate方法中,开始计时器,在surfaceDestoryed方法中,停止计时器,否则会引发异常

//surface创建时执行

@Override

public voidsurfaceCreated(SurfaceHolder holder) {

startTimer();

}

//surface意外销毁时执行

@Override

public voidsurfaceDestroyed(SurfaceHolder holder) {

//surface结束之后不停止timer,会出现异常

stopTimer();

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,932评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,554评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,894评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,442评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,347评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,899评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,325评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,980评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,196评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,163评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,085评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,826评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,389评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,501评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,753评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,171评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,616评论 2 339

推荐阅读更多精彩内容