Canvas裁剪和Region、RegionIterator
来源:互联网 发布:城市智能交通大数据 编辑:程序博客网 时间:2024/04/25 18:11
canvas 还提供裁剪的功能。
裁剪功能由Canvas提供的一系列的clip...方法 和quickReject方法来完成。 前面已经提到,真正提供可绘制区域的是Canvas内部的mutable bitmap。 Canvas更像是一个图层,我们只能在这上面的图层来绘制东西。
1、首先介绍Region类
Region,中文意思即区域的意思,它表示的是canvas图层上的某一块封闭的区域。
-
- public Region()
- public Region(Region region)
- public Region(Rect r)
- public Region(int left, int top, int right, int bottom)
-
-
- public void setEmpty() {
- public boolean set(Region region)
- public boolean set(Rect r)
- public boolean set(int left, int top, int right, int bottom)
-
- public boolean setPath(Path path, Region clip)
-
-
- public native boolean isEmpty();
- public native boolean isRect();
- public native boolean isComplex();
-
-
-
- public Rect getBounds()
- public boolean getBounds(Rect r)
- public Path getBoundaryPath()
- public boolean getBoundaryPath(Path path)
-
-
-
- public native boolean contains(int x, int y);
- public boolean quickContains(Rect r)
- public native boolean quickContains(int left, int top, int right,
- int bottom)
- public boolean quickReject(Rect r)
- public native boolean quickReject(int left, int top, int right, int bottom);
- public native boolean quickReject(Region rgn);
-
-
- public void translate(int dx, int dy)
- public native void translate(int dx, int dy, Region dst);
- public void scale(float scale)
- public native void scale(float scale, Region dst);
-
-
-
- public final boolean union(Rect r)
- public boolean op(Rect r, Op op) {
- public boolean op(int left, int top, int right, int bottom, Op op)
- public boolean op(Region region, Op op)
- public boolean op(Rect rect, Region region, Op op)
上面几乎是Region的所有API,很好理解,主要说明一下最后的一组关于Region组合的方式。组合即当前的Region和另外的一个Region组合,可以用不同的Op方式来进行组合。Op是一个枚举,定义在Region类中。
- 假设用region1 去组合region2
- public enum Op {
- DIFFERENCE(0),
- INTERSECT(1),
- UNION(2),
- XOR(3),
- REVERSE_DIFFERENCE(4),
- REPLACE(5);
- }
ApiDemo中已经提供了一个关于组合的例子,在最后面给出。
Android还提供了一个RegionIterator来对Region中的所有矩阵进行迭代,可以使用该类,获得某个Region的所有矩阵。比较简单。
2、什么是裁剪
裁剪Clip,即裁剪Canvas图层,我们绘制的东西,只能在裁剪区域的范围能才能显示出来。
- @Override
- protected void onDraw(Canvas canvas) {
- Paint paint=new Paint();
- canvas.save();
- canvas.clipRect(new Rect(100,100,300,300));
- canvas.drawColor(Color.BLUE);
- canvas.drawRect(new Rect(0,0,100,100), paint);
- canvas.drawCircle(150,150, 50, paint);
- canvas.restore();
- }
裁剪并不像Matrix变换,它相对于mutable bitmap的坐标是不会改变的。所以超出裁剪区域的绘制不会被显示
3、裁剪的保存和回滚
在之前已经提到了,canvas.save()和canvas.restore()不仅对matrix有效,同样对clip有类似的效果。
4、裁剪的方式
Canvas提供了三种裁剪的方式:
1、最基本的clipRect,裁剪一个矩形
2、clipPath,裁剪Path包括的范围,Path所包括的范围不是空的才有效。
3、clipRegion。
Region在前面已经介绍过了,其实Region就是一个对区域组合的一个封装。但是它和clipRect和clipPath的最大区别在于下面:
- Note that unlike
- clipRect() and clipPath() which transform their arguments by the
- current matrix, clipRegion() assumes its argument is already in the
- coordinate system of the current layer's bitmap, and so not
- transformation is performed.
与clipRect和clipPath要使用当前的matrix进行变换不同。clipRegion不会进行转换。也就是说canvas的matrix对clipRegion没有影响。- Paint paint=new Paint();
- canvas.scale(0.5f, 0.5f);
- canvas.save();
- canvas.clipRect(new Rect(100,100,200,200));
- canvas.drawColor(Color.RED);
- canvas.restore();
-
- canvas.drawRect(new Rect(0,0,100,100), paint);
-
- canvas.clipRegion(new Region(new Rect(300,300,400,400)));
- canvas.drawColor(Color.BLACK);
可以看到,Canvas的变换 对clipRegion没有作用。
ApiDemo中关于组合的例子:
- public class Clipping extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(new SampleView(this));
- }
-
- private static class SampleView extends View {
- private Paint mPaint;
- private Path mPath;
-
- public SampleView(Context context) {
- super(context);
- setFocusable(true);
-
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setStrokeWidth(6);
- mPaint.setTextSize(16);
- mPaint.setTextAlign(Paint.Align.RIGHT);
-
- mPath = new Path();
- }
-
- private void drawScene(Canvas canvas) {
- canvas.clipRect(0, 0, 100, 100);
-
- canvas.drawColor(Color.WHITE);
-
- mPaint.setColor(Color.RED);
- canvas.drawLine(0, 0, 100, 100, mPaint);
-
- mPaint.setColor(Color.GREEN);
- canvas.drawCircle(30, 70, 30, mPaint);
-
- mPaint.setColor(Color.BLUE);
- canvas.drawText("Clipping", 100, 30, mPaint);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawColor(Color.GRAY);
-
- canvas.save();
- canvas.translate(10, 10);
- drawScene(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.translate(160, 10);
- canvas.clipRect(10, 10, 90, 90);
- canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
- drawScene(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.translate(10, 160);
- mPath.reset();
- canvas.clipPath(mPath);
- mPath.addCircle(50, 50, 50, Path.Direction.CCW);
- canvas.clipPath(mPath, Region.Op.REPLACE);
- drawScene(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.translate(160, 160);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);
- drawScene(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.translate(10, 310);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
- drawScene(canvas);
- canvas.restore();
-
- canvas.save();
- canvas.translate(160, 310);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
- drawScene(canvas);
- canvas.restore();
- }
-
- }
- }
效果图:
5、裁剪的一个小用处
- public class ClippingRegion extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(new SampleView(this));
- }
-
- private class SampleView extends View {
-
- private Bitmap mBitmap;
- private int limitLength = 0;
- private int width;
- private int heigth;
- private static final int CLIP_HEIGHT = 30;
-
- private boolean status = HIDE;
- private static final boolean SHOW = true;
- private static final boolean HIDE = false;
-
- public SampleView(Context context) {
- super(context);
- mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
- limitLength = width = mBitmap.getWidth();
- heigth = mBitmap.getHeight();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- Region region = new Region();
- int i = 0;
- while (i * CLIP_HEIGHT <= heigth) {
- if (i % 2 == 0) {
- region.union(new Rect(0, i * CLIP_HEIGHT, limitLength, (i + 1) * CLIP_HEIGHT));
- } else {
- region.union(new Rect(width - limitLength, i * CLIP_HEIGHT, width, (i + 1)
- * CLIP_HEIGHT));
- }
- i++;
- }
-
- canvas.clipRegion(region);
- canvas.drawBitmap(mBitmap, 0, 0, new Paint());
- if (status == HIDE) {
- limitLength -= 5;
- if(limitLength<=0)
- status=SHOW;
- } else {
- limitLength += 5;
- if(limitLength>=width)
- status=HIDE;
- }
-
- invalidate();
- }
- }
- }
效果就是一直这样交叉的隐藏和显示图片
转载自:http://blog.csdn.net/lonelyroamer/article/details/8349601
0 0