首先最典型的就是随手而动的小球这个例子了,自制View,前提就是继承View,并且重写它的函数就行了
当View要绘制它的内容的时候就需要调用它的onDraw()函数了,这个函数的参数是画布Canvas类,与Swing编程非常类似,基本一看就明了。
public class DrawView extends View
{
public float x=40,y=50;
Paint paint=new Paint();
public DrawView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
public DrawView(Context context,AttributeSet set)
{
// TODO Auto-generated constructor stub
super(context, set);
}
@Override
protected void onDraw(Canvas canvas)
{
// TODO Auto-generated method stub
super.onDraw(canvas);
paint.setColor(Color.RED);
canvas.drawCircle(x, y, (float) 15.0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
// TODO Auto-generated method stub
x=event.getX();
y=event.getY();
invalidate();
return true;
}
}
如果你把它放到布局管理器中的时候需要用到第二个构造器,如果setContentView的时候直接用这个View就不用第二个构造器了。
除了View,另外还有SurfaceView是专门为2D游戏准备的视图类,其中SurfaceView只是保存当前视图像素数据,使用SurfaceView一般不直接和它打交道,而是通过SurfaceHolder来控制,通过它的lockCanvas()来获取画布,再在画布上修改内容来展示。
SurfaceHolder对SurfaceView监听时候需要Callback接口:
(1)当SurfaceView创建时回调的函数:public void surfaceCreated(SurfaceHolder arg0)
(2)当SurfaceView状态发生变化回调函数:public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
(3)当SurfaceView销毁时回调的函数:public void surfaceDestroyed(SurfaceHolder arg0)
一般的模型:
package com.example.playerproject;
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.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class MySurfaceView extends SurfaceView implements Callback
{
private SurfaceHolder sfh;
private boolean flag;
private MyThread thread;
private Canvas canvas;
private Paint paint;
private Bitmap bitmap;
public float robet_X,robet_Y,frameW,frameH,x,y;
private int curFrame;
public int direction;
final int Right=1;
final int left=-1;
class MyThread extends Thread
{
@Override
public void run()
{
while(flag)
{
long start=System.currentTimeMillis();
myDraw();
logic();
long end=System.currentTimeMillis();
if(end-start<50)
{
try
{
Thread.sleep(50-(end-start));
} catch (Exception e)
{
// TODO: handle exception
}
}
}
}
}
public MySurfaceView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
sfh=getHolder();
sfh.addCallback(this);
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder arg0)
{
// TODO Auto-generated method stub
thread=new MyThread();
flag=true;
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0)
{
// TODO Auto-generated method stub
}
private void myDraw()
{
// TODO Auto-generated method stub
try
{
canvas=sfh.lockCanvas();
if(canvas!=null)
{
}
} catch (Exception e)
{
// TODO: handle exception
}
finally{
if(canvas!=null)
{
sfh.unlockCanvasAndPost(canvas);
}
}
}
private void logic()
{
}
}
一般的模式就是在创建时回调的函数那里开一个线程,那个线程不停地调用MyDraw()--》logic()来修改画面内容,最后的Sleep()是用来确定一帧的时间的。
刷屏的方法:把画布用背景色染一次就行:canvas.drawColor(Color.BLACK);
SurfaceView的myDraw在另一线程中,而View的onDraw在本线程中,所以SurfaceView和View相比起来,更不容易引起ANR错误。
获取位图资源的办法:Bitmap bitmap=BitmapFactory.decodeResource(getResource(),ID);