首先介绍一下View类,View类是android的一个超类,每一个View都有一个用于绘画的画布,这个画布可以进行任意的扩展。有的时候我们需要自定义VIew实现自己想要的视图。view、SurfaceView是游戏开发中经常用到的视图。
View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。
SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比view快。
下面介绍一下View和SurfaceView区别:
View:必须在UI的主线程中更新画面,用于被动更新画面。
surfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。
先实现一个VIew的例子,新建一个MyView类基础View:
public class MyView extends View {
int count=0;
public int r=10; //圆的半径
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if(count<=100){
count++;
}else{
count=0;
}
//绘图
Paint paint=new Paint();
switch (count % 4) {
case 0:
paint.setColor(Color.BLUE);
break;
case 1:
paint.setColor(Color.YELLOW);
break;
case 2:
paint.setColor(Color.GRAY);
break;
case 3:
paint.setColor(Color.RED);
break;
default:
paint.setColor(Color.WHITE);
break;
}
canvas.drawCircle((320+r)/2, (480+r)/2, r, paint);
}
}
下面是需要显示它的TestViewActivity类:
invalidate
public class TestViewActivity extends Activity {
private MyView myView;
private int REFRESH;
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
if(msg.what==REFRESH){
myView.invalidate();
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
myView=new MyView(this);
setContentView(myView);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.sendEmptyMessage(REFRESH);
//使用postInvalidate可以直接在线程中更新UI界面
//myView.postInvalidate();
}
}
}).start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
myView.r+=2;
return super.onTouchEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode==KeyEvent.KEYCODE_BACK){
finish();
}
return super.onKeyDown(keyCode, event);
}
}
注释的部分是可以在线程中更新UI界面,当然也可以在handler中调用invalidate方法更新界面,这样就可以通过线程不断的重画改变小球的颜色,而且点击画面后小球会慢慢变大。
这是其中的一张截图:
下面看一下用SurfaceView是怎么实现的,照例创建一个MySurfaceView类:
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable {
SurfaceHolder surfaceHolder;
int count=0;
int r=10;
public MySurfaceView(Context context) {
super(context);
//实例化SurfaceHolder对象
surfaceHolder=this.getHolder();
//为SurfaceHolder添加一个回调函数
surfaceHolder.addCallback(this);
this.setFocusable(true);
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){ //死循环 来不停地画
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (surfaceHolder) {
Draw();
}
}
}
//绘图方法
public void Draw(){
//锁定画布 得到Canvas
Canvas canvas=surfaceHolder.lockCanvas();
if(surfaceHolder==null || canvas==null){
return ;
}
if(count<=100){
count++;
}else{
count=0;
}
Paint paint=new Paint();
switch (count % 4) {
case 0:
paint.setColor(Color.BLUE);
break;
case 1:
paint.setColor(Color.YELLOW);
break;
case 2:
paint.setColor(Color.GRAY);
break;
case 3:
paint.setColor(Color.RED);
break;
default:
paint.setColor(Color.WHITE);
break;
}
canvas.drawCircle((320+r)/2, (480+r)/2, r, paint);
//解锁画布
surfaceHolder.unlockCanvasAndPost(canvas);
}
//在surface大小改变时激发
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
//在surface创建时激发
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
//开启视图线程
new Thread(this).start();
}
//在surface销毁时激发
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
SurfaceView不需要通过线程来更新视图,但在绘图之前必须使用lockCanvas方法锁定画布,并得到画布,然后在画布上绘制;当绘制完成后,使用unlockCanvasAndPost方法来解锁画布,这样才能显示在屏幕上。
public class TestSurfaceViewActivity extends Activity {
MySurfaceView mySurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mySurfaceView=new MySurfaceView(this);
setContentView(mySurfaceView);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
mySurfaceView.r+=2;
return super.onTouchEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode==KeyEvent.KEYCODE_BACK){
finish();
}
return super.onKeyDown(keyCode, event);
}
}
运行效果和上面的一样,就不做演示了。