在android中实现自定义的view来画图存在以下两个缺陷:
1)view缺乏双缓冲机制
2)当程序需要更新view上的视图时,必须重绘整张图片
由于上述缺陷,在程序尤其是游戏中,绘图的性能并不理想,android为此提供了SurfaceView。
SurfaceView一般和SurfaceHolder结合一起使用,SurfaceHolder用于在向与之关联的SurfaceView上绘图,获取SurfaceHolder的方法如下:
1)Canvas lockCanvas()//获取整个画布
2)Canvas lockCanvas(Rect dirty)//获取指定矩形画布,即只更新指定区域,从而提高更新速度
程序画完图后需要用unlockCanvasAndPost(canvas)来释放绘图、提交所绘制的图形。需要注意的是,解锁之后,该方法绘制的图形还处于缓冲之中,下一次lockCanvas()可能会覆盖它,解决方法可以是让绘制线程等待一下,或者是锁定一个Rect(0,0,0,0)等等。
下面给出一段代码来介绍其具体用法,相应地方会加上注释
public class WelcomeView extends SurfaceView implements SurfaceHolder.Callback
{
MainActivity activity;
Paint paint;
Bitmap[] logos=new Bitmap[2];
Bitmap currentLogo=null;
int currentX,currentY;
int currentAlpha=0;
int screenWidth=480;
int screenHeight=800;
int sleep=50;
public WelcomeView(MainActivity activity)
{
super(activity);
// TODO Auto-generated constructor stub
this.activity=activity;
this.getHolder().addCallback(this);//设置回调借口的实现者,必须实现,否则没有回调,那么无论如何都不会画图
paint=new Paint();
paint.setAntiAlias(true);
logos[0]=BitmapFactory.decodeResource(activity.getResources(), R.drawable.dukea);
logos[1]=BitmapFactory.decodeResource(activity.getResources(), R.drawable.dukeb);
}
public void onDraw(Canvas canvas)//画图的代码
{
Log.d("DEBUG", "drawing");
paint.setColor(Color.BLACK);
paint.setAlpha(255);
canvas.drawRect(0, 0, screenWidth, screenHeight, paint);
if(currentLogo==null)return;
paint.setAlpha(currentAlpha);
canvas.drawBitmap(currentLogo, currentX, currentY, paint);
}
@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
new Thread()
{
@SuppressLint("WrongCall")
public void run()
{
for(Bitmap bm:logos)
{
currentLogo=bm;
currentX=screenWidth/2-bm.getWidth()/2;
currentY=screenHeight/2-bm.getHeight()/2;
for(int i=255;i>-10;i-=10)
{
currentAlpha=i;
if(currentAlpha<0)
currentAlpha=0;
SurfaceHolder holder=WelcomeView.this.getHolder();
Canvas canvas=holder.lockCanvas();
try
{
synchronized(holder)
{
onDraw(canvas);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(canvas!=null)
holder.unlockCanvasAndPost(canvas);
}
try
{
if(i==255)//若是新图片,多等待一会
{
Thread.sleep(1000);
}
Thread.sleep(sleep)//线程等待一会;
}catch(Exception e){
e.printStackTrace();
}
}
}
activity.handler.sendEmptyMessage(0);
}
}.start();
}
注意到一点就是与SurfaceView关联的holder设置一个callback回调函数,来对创造SurfaceView或者改动它等进行回调操作,进而达到绘图的目的