canvas 的cliprect()能够对画布实现剪切,显示需要的可见区域,除了此区域之外的地方其任何内容都不可见,这个区域可以是矩形也可以是圆。
这个demo简单用了一张图片在画布中使用cliprect方法剪切了一部分,需要注意的是要用到 save()和restore()两个成对出现的方法!其实对剪切的操作就是在这两个方法之间进行的,简单的说就是在cliprect设置了可见区域后,在这个可见区域内进行的操作能够保留下来,不在这个区域内操作的东西通过restore()方法就把它“清除掉了”
public class MSurfaceView extends SurfaceView implements Callback, Runnable{ private SurfaceHolder holder; private Paint paint, paintFont; private Thread mThread; private Canvas canvas; private boolean state; private int x, y; private int window_x, window_y; private final static int MAX_TIME = 80; private Bitmap mBitmap, backBitmap; public MSurfaceView(Context context) { super(context); // TODO Auto-generated constructor stub holder = this.getHolder(); paint = new Paint(); paintFont = new Paint(); paint.setColor(Color.BLUE); paintFont.setColor(Color.WHITE); holder.addCallback(this); setFocusable(true); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub Log.v("tag", "surfacechanged"); } @Override public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub Log.v("tag", "surfacecreated"); window_x = this.getWidth(); window_y = this.getHeight(); state = true; mThread = new Thread(this); mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub Log.v("tag", "surfacedestoryed"); state = false; } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub x = (int)event.getX(); y = (int)event.getY(); return true; } public void mDraw(){ try { canvas = holder.lockCanvas(); // if (canvas != null) { // backBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.okc); // canvas.drawBitmap(backBitmap, 0, 0, paint); canvas.drawRGB(0, 0, 0); mBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.ic_launcher); canvas.drawBitmap(mBitmap, x, y, paint); Log.v("tag", "绘制位图"); canvas.save(); canvas.clipRect(0, 0, 200, 200); backBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.okc); canvas.drawBitmap(backBitmap, 0, 0, paint); // canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), paint); // canvas.translate(10, 10); // canvas.drawBitmap(mBitmap, 50, 50, paint); canvas.restore(); // canvas.drawCircle(x, y, getradius(), paint); // canvas.drawText("坐标值:" + x, 30, 30, paintFont); // canvas.drawText("坐标值:" + y, 40, 40, paintFont); // } } catch (Exception e) { // TODO: handle exception }finally{ if (canvas != null) { holder.unlockCanvasAndPost(canvas); } } } private int getradius(){ int r = (int)(Math.random()*30); return r; } @Override public void run() { // TODO Auto-generated method stub while(state){ long start = System.currentTimeMillis(); mDraw(); long end = System.currentTimeMillis(); if ((end - start) < MAX_TIME) { try { Thread.sleep(MAX_TIME - (end - start)); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
用MainActivity.java显示当前的view:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new MSurfaceView(this)); } }
第一张时剪切后的效果,第二张是原始图片
哈哈哈 图片有点太大了 没管那么多
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
下面再通过另外一种方式实现画布剪切,这次剪切一个圆形区域,使用path:
canvas.save(); Path path = new Path(); path.addCircle(40, 50, 30, Direction.CCW); canvas.clipPath(path); backBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.okc); canvas.drawBitmap(backBitmap, 0, 0 ,paint); canvas.restore();
首先实例化path,然后添加一个指定大小的circle并将这个circle作为我们所要的可见区域,再在屏幕上面绘制我们的图片,然后使用restore方法,“清除”掉我们绘制时候没有在可见区域内的操作,最后看到的效果如下: