1、首先介绍Region类

Region,中文意思即区域的意思,它表示的是canvas图层上的某一块封闭的区域。

  1. /**构造方法*/
  2. public Region()  //创建一个空的区域
  3. public Region(Region region) //拷贝一个region的范围
  4. public Region(Rect r)  //创建一个矩形的区域
  5. public Region(int left, int top, int right, int bottom) //创建一个矩形的区域
  6. /**一系列set方法,这些set方法,和上面构造方法形式差不多*/
  7. public void setEmpty() {
  8. public boolean set(Region region)
  9. public boolean set(Rect r)
  10. public boolean set(int left, int top, int right, int bottom)
  11. /*往一个Region中添加一个Path只有这种方法,参数clip代表这个整个Region的区域,在在里面裁剪出path范围的区域*/
  12. public boolean setPath(Path path, Region clip) //用指定的Path和裁剪范围构建一个区域
  13. /**几个判断方法*/
  14. public native boolean isEmpty();//判断该区域是否为空
  15. public native boolean isRect(); //是否是一个矩阵
  16. public native boolean isComplex();//是否是多个矩阵组合
  17. /**一系列的getBound方法,返回一个Region的边界*/
  18. public Rect getBounds()
  19. public boolean getBounds(Rect r)
  20. public Path getBoundaryPath()
  21. public boolean getBoundaryPath(Path path)
  22. /**一系列的判断是否包含某点 和是否相交*/
  23. public native boolean contains(int x, int y);//是否包含某点
  24. public boolean quickContains(Rect r)   //是否包含某矩阵
  25. public native boolean quickContains(int left, int top, int right,
  26. int bottom) //是否没有包含某矩阵
  27. public boolean quickReject(Rect r) //是否没和该矩阵相交
  28. public native boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩阵相交
  29. public native boolean quickReject(Region rgn);  //是否没和该矩阵相交
  30. /**几个平移变换的方法*/
  31. public void translate(int dx, int dy)
  32. public native void translate(int dx, int dy, Region dst);
  33. public void scale(float scale) //hide
  34. public native void scale(float scale, Region dst);//hide
  35. /**一系列组合的方法*/
  36. public final boolean union(Rect r)
  37. public boolean op(Rect r, Op op) {
  38. public boolean op(int left, int top, int right, int bottom, Op op)
  39. public boolean op(Region region, Op op)
  40. public boolean op(Rect rect, Region region, Op op)
/**构造方法*/
public Region() //创建一个空的区域
public Region(Region region) //拷贝一个region的范围
public Region(Rect r) //创建一个矩形的区域
public Region(int left, int top, int right, int bottom) //创建一个矩形的区域 /**一系列set方法,这些set方法,和上面构造方法形式差不多*/
public void setEmpty() {
public boolean set(Region region)
public boolean set(Rect r)
public boolean set(int left, int top, int right, int bottom)
/*往一个Region中添加一个Path只有这种方法,参数clip代表这个整个Region的区域,在在里面裁剪出path范围的区域*/
public boolean setPath(Path path, Region clip) //用指定的Path和裁剪范围构建一个区域 /**几个判断方法*/
public native boolean isEmpty();//判断该区域是否为空
public native boolean isRect(); //是否是一个矩阵
public native boolean isComplex();//是否是多个矩阵组合 /**一系列的getBound方法,返回一个Region的边界*/
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) //hide
public native void scale(float scale, Region dst);//hide /**一系列组合的方法*/
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类中。

  1. 假设用region1  去组合region2
  2. public enum Op {
  3. DIFFERENCE(0), //最终区域为region1 与 region2不同的区域
  4. INTERSECT(1), // 最终区域为region1 与 region2相交的区域
  5. UNION(2),      //最终区域为region1 与 region2组合一起的区域
  6. XOR(3),        //最终区域为region1 与 region2相交之外的区域
  7. REVERSE_DIFFERENCE(4), //最终区域为region2 与 region1不同的区域
  8. REPLACE(5); //最终区域为为region2的区域
  9. }
假设用region1  去组合region2
public enum Op {
DIFFERENCE(0), //最终区域为region1 与 region2不同的区域
INTERSECT(1), // 最终区域为region1 与 region2相交的区域
UNION(2), //最终区域为region1 与 region2组合一起的区域
XOR(3), //最终区域为region1 与 region2相交之外的区域
REVERSE_DIFFERENCE(4), //最终区域为region2 与 region1不同的区域
REPLACE(5); //最终区域为为region2的区域
}

ApiDemo中已经提供了一个关于组合的例子,在最后面给出。

Android还提供了一个RegionIterator来对Region中的所有矩阵进行迭代,可以使用该类,获得某个Region的所有矩阵。比较简单。

2、什么是裁剪

裁剪Clip,即裁剪Canvas图层,我们绘制的东西,只能在裁剪区域的范围能才能显示出来。

  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. Paint paint=new Paint();
  4. canvas.save();
  5. canvas.clipRect(new Rect(100,100,300,300));
  6. canvas.drawColor(Color.BLUE);//裁剪区域的rect变为蓝色
  7. canvas.drawRect(new Rect(0,0,100,100), paint);//在裁剪的区域之外,不能显示
  8. canvas.drawCircle(150,150, 50, paint);//在裁剪区域之内,能显示
  9. canvas.restore();
  10. }
@Override
protected void onDraw(Canvas canvas) {
Paint paint=new Paint();
canvas.save();
canvas.clipRect(new Rect(100,100,300,300));
canvas.drawColor(Color.BLUE);//裁剪区域的rect变为蓝色
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的最大区别在于下面:

  1. Note that unlike
  2. clipRect() and clipPath() which transform their arguments by the
  3. current matrix, clipRegion() assumes its argument is already in the
  4. coordinate system of the current layer's bitmap, and so not
  5. transformation is performed.
  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没有影响。

  1. Paint paint=new Paint();
  2. canvas.scale(0.5f, 0.5f);
  3. canvas.save();
  4. canvas.clipRect(new Rect(100,100,200,200));//裁剪区域实际大小为50*50
  5. canvas.drawColor(Color.RED);
  6. canvas.restore();
  7. canvas.drawRect(new Rect(0,0,100,100), paint);//矩形实际大小为50*50
  8. canvas.clipRegion(new Region(new Rect(300,300,400,400)));//裁剪区域实际大小为100*100
  9. canvas.drawColor(Color.BLACK);
           Paint paint=new Paint();
canvas.scale(0.5f, 0.5f);
canvas.save();
canvas.clipRect(new Rect(100,100,200,200));//裁剪区域实际大小为50*50
canvas.drawColor(Color.RED);
canvas.restore(); canvas.drawRect(new Rect(0,0,100,100), paint);//矩形实际大小为50*50 canvas.clipRegion(new Region(new Rect(300,300,400,400)));//裁剪区域实际大小为100*100
canvas.drawColor(Color.BLACK);

可以看到,Canvas的变换 对clipRegion没有作用。

ApiDemo中关于组合的例子:

  1. public class Clipping extends Activity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(new SampleView(this));
  6. }
  7. private static class SampleView extends View {
  8. private Paint mPaint;
  9. private Path mPath;
  10. public SampleView(Context context) {
  11. super(context);
  12. setFocusable(true);
  13. mPaint = new Paint();
  14. mPaint.setAntiAlias(true);
  15. mPaint.setStrokeWidth(6);
  16. mPaint.setTextSize(16);
  17. mPaint.setTextAlign(Paint.Align.RIGHT);
  18. mPath = new Path();
  19. }
  20. private void drawScene(Canvas canvas) {
  21. canvas.clipRect(0, 0, 100, 100);
  22. canvas.drawColor(Color.WHITE);
  23. mPaint.setColor(Color.RED);
  24. canvas.drawLine(0, 0, 100, 100, mPaint);
  25. mPaint.setColor(Color.GREEN);
  26. canvas.drawCircle(30, 70, 30, mPaint);
  27. mPaint.setColor(Color.BLUE);
  28. canvas.drawText("Clipping", 100, 30, mPaint);
  29. }
  30. @Override
  31. protected void onDraw(Canvas canvas) {
  32. canvas.drawColor(Color.GRAY);
  33. canvas.save();
  34. canvas.translate(10, 10);
  35. drawScene(canvas);
  36. canvas.restore();
  37. canvas.save();
  38. canvas.translate(160, 10);
  39. canvas.clipRect(10, 10, 90, 90);
  40. canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
  41. drawScene(canvas);
  42. canvas.restore();
  43. canvas.save();
  44. canvas.translate(10, 160);
  45. mPath.reset();
  46. canvas.clipPath(mPath); // makes the clip empty
  47. mPath.addCircle(50, 50, 50, Path.Direction.CCW);
  48. canvas.clipPath(mPath, Region.Op.REPLACE);
  49. drawScene(canvas);
  50. canvas.restore();
  51. canvas.save();
  52. canvas.translate(160, 160);
  53. canvas.clipRect(0, 0, 60, 60);
  54. canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);
  55. drawScene(canvas);
  56. canvas.restore();
  57. canvas.save();
  58. canvas.translate(10, 310);
  59. canvas.clipRect(0, 0, 60, 60);
  60. canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
  61. drawScene(canvas);
  62. canvas.restore();
  63. canvas.save();
  64. canvas.translate(160, 310);
  65. canvas.clipRect(0, 0, 60, 60);
  66. canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
  67. drawScene(canvas);
  68. canvas.restore();
  69. }
  70. }
  71. }
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); // makes the clip empty
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、裁剪的一个小用处

  1. public class ClippingRegion extends Activity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(new SampleView(this));
  6. }
  7. private class SampleView extends View {
  8. private Bitmap mBitmap;
  9. private int limitLength = 0;
  10. private int width;
  11. private int heigth;
  12. private static final int CLIP_HEIGHT = 30;
  13. private boolean status = HIDE;//显示还是隐藏的状态,最开始为HIDE
  14. private static final boolean SHOW = true;//显示图片
  15. private static final boolean HIDE = false;//隐藏图片
  16. public SampleView(Context context) {
  17. super(context);
  18. mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
  19. limitLength = width = mBitmap.getWidth();
  20. heigth = mBitmap.getHeight();
  21. }
  22. @Override
  23. protected void onDraw(Canvas canvas) {
  24. Region region = new Region();
  25. int i = 0;
  26. while (i * CLIP_HEIGHT <= heigth) {//计算clip的区域
  27. if (i % 2 == 0) {
  28. region.union(new Rect(0, i * CLIP_HEIGHT, limitLength, (i + 1) * CLIP_HEIGHT));
  29. } else {
  30. region.union(new Rect(width - limitLength, i * CLIP_HEIGHT, width, (i + 1)
  31. * CLIP_HEIGHT));
  32. }
  33. i++;
  34. }
  35. canvas.clipRegion(region);
  36. canvas.drawBitmap(mBitmap, 0, 0, new Paint());
  37. if (status == HIDE) {//如果此时是隐藏
  38. limitLength -= 5;
  39. if(limitLength<=0)
  40. status=SHOW;
  41. } else {//如果此时是显示
  42. limitLength += 5;
  43. if(limitLength>=width)
  44. status=HIDE;
  45. }
  46. invalidate();
  47. }
  48. }
  49. }
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;//显示还是隐藏的状态,最开始为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) {//计算clip的区域
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();
}
}
}

效果就是一直这样交叉的隐藏和显示图片

Android 2D Graphics学习 Region和Canvas裁剪的更多相关文章

  1. Android使用学习之画图(Canvas,Paint)与手势感应及其应用(乒乓球小游戏)

    作为一个没有学习Android的菜鸟,近期一直在工作之外努力地学习的Android的使用. 这周看了下Android的画图.主要是Canvas,Paint等,感觉须要实践下.下午正好有空,就想整一个乒 ...

  2. Canvas裁剪和Region、RegionIterator

    主要是看这边文章学习:http://blog.csdn.net/lonelyroamer/article/details/8349601 Region.op参数 DIFFERENCE(0), //最终 ...

  3. android开源项目学习

    FBReaderJ FBReaderJ用于Android平台的电子书阅读器,它支持多种电子书籍格式包括:oeb.ePub和fb2.此外还支持直接读取zip.tar和gzip等压缩文档. 项目地址:ht ...

  4. Android 2D绘图初步

    Android是通过graphics类来显示2D图形的.其中graphics中包括了Canvas.Paint.Color.Bitmap等类.graphics具有绘制点.线.颜色.2D几何图形.图像处理 ...

  5. Android Drawable绘图学习笔记(转)

    如何获取 res 中的资源 数据包package:android.content.res 主要类:Resources Android SDK中的简介:Class for accessing an ap ...

  6. Android之SurfaceView学习(一)转转

    Android之SurfaceView学习(一) 首先我们先来看下官方API对SurfaceView的介绍 SurfaceView的API介绍 Provides a dedicated drawing ...

  7. HTML5移动开发学习笔记之Canvas基础

    1.第一个Canvas程序 看的是HTML5移动开发即学即用这本书,首先学习Canvas基础,废话不多说,直接看第一个例子. 效果图为: 代码如下: <!DOCTYPE html> < ...

  8. Android Paint Xfermode 学习小结

    一.setXfermode(Xfermode xfermode) Xfermode国外有大神称之为过渡模式,这种翻译比较贴切但恐怕不易理解,大家也可以直接称之为图像混合模式,因为所谓的"过渡 ...

  9. html5 canvas裁剪区域

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

随机推荐

  1. xml dtd 定义元素

    ANY 如果需要定义某个元素的值可以是任意类型,可采用如下语法 <!ELEMENT 元素名 ANY> DTD必须定义XML文档中允许出现的所有元素,所以下面这样是不行的,因为<hel ...

  2. CountDownLatch

    使用的实例: @Override public <V> V get(Future<V> future) { final CountDownLatch l = new Count ...

  3. bootstrap 20161012

    栅格系统 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="u ...

  4. js验证输入的金钱格式

    <html> <head> <title>js验证输入的金钱格式</title> <script type="text/javascri ...

  5. 【Cocos2d-x for WP8 学习整理】(1)创建一个新项目

    喜大普奔                         10.1假期之前看到了一个很振奋的消息,就是随着Cocos2d-x 2.2的发布,WP8/WIN8有史以来第一次的合并到主版本了. 之前 V2 ...

  6. Fzu2124 - 吃豆人 BFS

    Description 吃豆人是一款非常经典的游戏,游戏中玩家控制吃豆人在地图上吃光所有豆子,并且避免被怪物抓住. 这道题没有怪物,将游戏的画面分成n*m的格子,每格地形可能为空地或者障碍物,吃豆人可 ...

  7. iOS ---不一样的NSLog打印(精准打印)

    在iOS开发过程中,调试是很重要的过程,而除了各种断点调试(普通断点.条件断点.全局断点)之外,似乎NSLog是我们调试最常用的方法,当然,也是最简单朴素的寻debug方法. 在项目中,我们常使用的N ...

  8. HDU5730 Shell Necklace(DP + CDQ分治 + FFT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5730 Description Perhaps the sea‘s definition of ...

  9. 集中式vs分布式区别

    记录一下我了解到的版本控制系统,集中式与分布式,它们之间的区别做下个人总结. 什么是集中式? 集中式开发:是将项目集中存放在中央服务器中,在工作的时候,大家只在自己电脑上操作,从同一个地方下载最新版本 ...

  10. MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划

    这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...