(1)直接在UI线程中调用invalidate()
public class GameView extends View { private int cx; private int cy; private Paint p; public GameView(Context context) { super(context); this.cx = 20; this.cy = 20; this.p = new Paint(); p.setColor(Color.RED); } @Override protected void onDraw(Canvas canvas) { canvas.drawCircle(cx, cy, 10, p); } @Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: //返回false,则该事件消失且接收不到下次事件 return true; case MotionEvent.ACTION_UP: int x = (int)event.getX(); int y = (int)event.getY(); changePosition(x, y); return true; } return super.onTouchEvent(event); } private void changePosition(int x,int y) { this.cx = x; this.cy = y; this.invalidate(); } }
public class GameView extends View { //..... @Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: return true; case MotionEvent.ACTION_UP: int x = (int)event.getX(); int y = (int)event.getY(); GameThread gameThread = new GameThread(x,y); gameThread.start(); return true; } return super.onTouchEvent(event); } private Handler mHandler = new Handler() { public void handleMessage(Message msg) { changePosition(msg.arg1, msg.arg2); } }; private class GameThread extends Thread { private int x; private int y; public GameThread(int x,int y) { this.x = x; this.y = y; } public void run() { Message msg = mHandler.obtainMessage(); msg.arg1 = x; msg.arg2 = y; msg.sendToTarget(); } } }
@Override public boolean onTouchEvent(MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: return true; case MotionEvent.ACTION_UP: int x = (int)event.getX(); int y = (int)event.getY(); GameThread gameThread = new GameThread(x,y); gameThread.start(); return true; } return super.onTouchEvent(event); } private void changePosition(int x,int y) { this.cx = x; this.cy = y; } private class GameThread extends Thread { private int x; private int y; public GameThread(int x,int y) { this.x = x; this.y = y; } public void run() { changePosition(x, y); postInvalidate(); } }
public void postInvalidate() { postInvalidateDelayed(0); } public void postInvalidateDelayed(long delayMilliseconds) { // We try only with the AttachInfo because there's no point in invalidating // if we are not attached to our window final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); } } public void dispatchInvalidateDelayed(View view, long delayMilliseconds) { Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view); mHandler.sendMessageDelayed(msg, delayMilliseconds); }
从上面的代码可以看到,使用了mHandler去更新UI,mHandler是ViewRootHandler的一个实例,它是在UI线程中创建的。
(4)view实现双缓冲技术
当数据量比较大,绘图时间比较长时,重复绘图会出现闪烁现象,引起闪烁现象的主要原因是视觉反差比较大。使用双缓冲技术可以解决这个问题,Surfaceview默认是使用双缓冲技术的。在Android上实现双缓冲技术的步骤是:创建一个屏幕大小(实际绘图区域)的缓冲区(Bitmap),创建一个画布(Canvas),然后设置画布的bitmap为创建好的缓冲区,把需要绘制的图像绘制到缓冲区上。最后把缓冲区中的图像绘制到屏幕上。具体实现代码如下:
public Bitmap decodeBitmapFromRes(Context context, int resourseId) { BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferredConfig = Config.ARGB_8888; opt.inPurgeable = true; opt.inInputShareable = true; InputStream is = context.getResources().openRawResource(resourseId); return BitmapFactory.decodeStream(is, null, opt); } @Override protected void onDraw(Canvas canvas) { Canvas bufferCanvas = new Canvas(); Bitmap bitmap = Bitmap.createBitmap(320, 480, Config.ARGB_8888); Bitmap img = decodeBitmapFromRes(mContext, R.drawable.sprite); bufferCanvas.setBitmap(bitmap); bufferCanvas.drawBitmap(img, 0, 0, null); canvas.drawBitmap(bitmap, 0, 0, null); }
public enum Config { ALPHA_8 (2), RGB_565 (4), @Deprecated ARGB_4444 (5), ARGB_8888 (6); final int nativeInt; @SuppressWarnings({"deprecation"}) private static Config sConfigs[] = { null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888 }; Config(int ni) { this.nativeInt = ni; } static Config nativeToConfig(int ni) { return sConfigs[ni]; } }
转载请注明来自:Alex Zhou,本文链接:http://codingnow.cn/android/594.html