展会信息港展会大全

Android中SurfaceView学习
来源:互联网   发布日期:2015-10-03 15:17:48   浏览:2005次  

导读: SurfaceView和View的明显不同在于Surface不需要通过线程来更新视图,但在绘制之前必须使用lockCanvas方法锁定画布,并得 到画布,然后绘制,完成后用unlockCa...

SurfaceView和View的明显不同在于Surface不需要通过线程来更新视图,但在绘制之前必须使用lockCanvas方法锁定画布,并得 到画布,然后绘制,完成后用unlockCanvasAndPost方法解锁画布。SurfaceView类的事件处理和View一样。

首先来看一个简单的框架。

绘制界面类:

[java]

package com.example.bonusball;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

public class CanvasView extends SurfaceView implements SurfaceHolder.Callback

{

private SurfaceHolder myHolder;

private Paint ballPaint; // Paint used to draw the cannonball

private int screenWidth; // width of the screen

private int screenHeight; // height of the screen

private int ballRadius;

private CanvasThread myThread;

//控制循环

private boolean isLoop;

public CanvasView(Context context) {

super(context);

// TODO Auto-generated constructor stub

myHolder=this.getHolder();

myHolder.addCallback(this);

ballPaint=new Paint();

ballPaint.setColor(Color.BLUE);

isLoop = true;

}

public void fireBall(float startX,float startY)

{

System.out.println("Fire");

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

// TODO Auto-generated method stub

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh)

{

super.onSizeChanged(w, h, oldw, oldh);

screenWidth = w; // store the width

screenHeight = h; // store the height

ballRadius=w/10;

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

// TODO Auto-generated method stub

myThread = new CanvasThread();

System.out.println("SurfaceCreated!");

myThread.start();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// TODO Auto-generated method stub

// 停止循环

isLoop = false;

}

public void drawGameElements(Canvas canvas)

{

canvas.drawCircle(100, 100,ballRadius,ballPaint);

}

private class CanvasThread extends Thread

{

@Override

public void run()

{

while(true)

{

synchronized( myHolder )

{

Canvas canvas = myHolder.lockCanvas(null);//获取画布

drawGameElements(canvas);

myHolder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像

//System.out.println("run");

}

}

}

}

}

package com.example.bonusball;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.RectF;

import android.util.AttributeSet;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

public class CanvasView extends SurfaceView implements SurfaceHolder.Callback

{

private SurfaceHolder myHolder;

private Paint ballPaint; // Paint used to draw the cannonball

private int screenWidth; // width of the screen

private int screenHeight; // height of the screen

private int ballRadius;

private CanvasThread myThread;

//控制循环

private boolean isLoop;

public CanvasView(Context context) {

super(context);

// TODO Auto-generated constructor stub

myHolder=this.getHolder();

myHolder.addCallback(this);

ballPaint=new Paint();

ballPaint.setColor(Color.BLUE);

isLoop = true;

}

public void fireBall(float startX,float startY)

{

System.out.println("Fire");

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

// TODO Auto-generated method stub

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh)

{

super.onSizeChanged(w, h, oldw, oldh);

screenWidth = w; // store the width

screenHeight = h; // store the height

ballRadius=w/10;

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

// TODO Auto-generated method stub

myThread = new CanvasThread();

System.out.println("SurfaceCreated!");

myThread.start();

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// TODO Auto-generated method stub

// 停止循环

isLoop = false;

}

public void drawGameElements(Canvas canvas)

{

canvas.drawCircle(100, 100,ballRadius,ballPaint);

}

private class CanvasThread extends Thread

{

@Override

public void run()

{

while(true)

{

synchronized( myHolder )

{

Canvas canvas = myHolder.lockCanvas(null);//获取画布

drawGameElements(canvas);

myHolder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像

//System.out.println("run");

}

}

}

}

}

事件处理 类:

[java]

package com.example.bonusball;

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Rect;

import android.view.GestureDetector;

import android.view.GestureDetector.SimpleOnGestureListener;

import android.view.MotionEvent;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.widget.Toast;

public class BallActivity extends Activity {

private GestureDetector myGestureDetector;//监听手势

private CanvasView myCanvas;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

myCanvas=new CanvasView(this);

setContentView(myCanvas);

myGestureDetector = new GestureDetector(this, new MyGestureListener());

}

@Override

public boolean onTouchEvent(MotionEvent event)

{

return myGestureDetector.onTouchEvent(event);

}

private class MyGestureListener extends SimpleOnGestureListener

{

public boolean onDown(MotionEvent e1) {

Toast.makeText(getApplicationContext(), "onDown", Toast.LENGTH_SHORT).show();

return true;

}

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

{

System.out.println("Fling");

return true;

}

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_ball, menu);

return true;

}

}

package com.example.bonusball;

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Rect;

import android.view.GestureDetector;

import android.view.GestureDetector.SimpleOnGestureListener;

import android.view.MotionEvent;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.widget.Toast;

public class BallActivity extends Activity {

private GestureDetector myGestureDetector;//监听手势

private CanvasView myCanvas;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

myCanvas=new CanvasView(this);

setContentView(myCanvas);

myGestureDetector = new GestureDetector(this, new MyGestureListener());

}

@Override

public boolean onTouchEvent(MotionEvent event)

{

return myGestureDetector.onTouchEvent(event);

}

private class MyGestureListener extends SimpleOnGestureListener

{

public boolean onDown(MotionEvent e1) {

Toast.makeText(getApplicationContext(), "onDown", Toast.LENGTH_SHORT).show();

return true;

}

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

{

System.out.println("Fling");

return true;

}

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_ball, menu);

return true;

}

}

解释几个 概念 :

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绘制过程中不会被改变(被摧毁、修改)。

最后来看一个复杂一些的例子 ,结合了之前的手势操作。

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港