Android 绘图基础四 Region

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

Region 常用Api

1、基本构造函数

构造函数只能传入矩形 或者region

 public Region()  //创建一个空的区域  
 public Region(Region region) //拷贝一个region的范围  
 public Region(Rect r)  //创建一个矩形的区域  
 public Region(int left, int top, int right, int bottom) //创建一个矩形的区域  

2、间接构造

只能为region 设置矩形或者其他的region,综合上面的构造方法,Region只能设置矩形区域

 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)//后面单独讲

这是Region所具有的一系列Set方法,我这里全部列了出来,下面一一对其讲解:

注意:无论调用Set系列函数的Region是不是有区域值,当调用Set系列函数后,原来的区域值就会被替换成Set函数里的区域。

  • SetEmpty():从某种意义上讲置空也是一个构造函数,即将原来的一个区域变量变成了一个空变量,要再利用其它的Set方法重新构造区域。
  • set(Region region):利用新的区域值来替换原来的区域
  • set(Rect r):利用矩形所代表的区域替换原来的区域
  • set(int left, int top, int right, int bottom):同样,根据矩形的两个点构造出矩形区域来替换原来的区域值
  • setPath(Path path, Region clip):根据路径的区域与某区域的交集,构造出新区域,这个后面具体讲解

3、矩形集枚举区域——RegionIterator类

对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;

RegionIterator(Region region) //根据区域构建对应的矩形集
boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中

由于在Canvas中没有直接绘制Region的函数,我们想要绘制一个区域,就只能通过利用RegionIterator构造矩形集来逼近的显示区域。用法如下:


 // 用矩形画椭圆
    public void drawOvalUseRect(Canvas canvas){
        // 2.0 区域由很多矩形构成
        //初始化Paint
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        //构造一个椭圆路径
        Path ovalPath = new Path();
        RectF rect =  new RectF(50, 50, 200, 500);
        ovalPath.addOval(rect, Path.Direction.CCW);
        //SetPath时,传入一个比椭圆区域小的矩形区域,让其取交集
        Region rgn = new Region();
        rgn.setPath(ovalPath,new  Region(50, 50, 200, 500));
        //画出路径
        drawRegion(canvas, rgn, paint);
    }

private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
{  
    RegionIterator iter = new RegionIterator(rgn);  
    Rect r = new Rect(); 
    while (iter.next(r)) {  
      canvas.drawRect(r, paint);  
    }   
}  

上面我们也都看到了它的用法,首先,根据区域构建一个矩形集,然后利用next(Rect r)来逐个获取所有矩形,绘制出来,最终得到的就是整个区域,如果我们将上面的画笔Style从FILL改为STROKE,重新绘制椭圆路径,会看得更清楚。


4、使用SetPath()构造不规则区域

boolean setPath (Path path, Region clip)
参数说明:Path path:用来构造的区域的路径
Region clip:与前面的path所构成的路径取交集,并将两交集设置为最终的区域

由于路径有很多种构造方法,而且可以轻意构造出非矩形的路径,这就摆脱了前面的构造函数只能构造矩形区域的限制。但这里有个问题是要指定另一个区域来取共同的交集,当然如果想显示路径构造的区域,Region clip参数可以传一个比Path范围大的多的区域,取完交集之后,当然是Path参数所对应的区域喽。机智的孩子。

下面,先构造一个椭圆路径,然后在SetPath时,传进去一个比Path小的矩形区域,让它们两个取交集

public class MyRegionView extends View {  
 
   public MyRegionView(Context context) {  
       super(context);  
       // TODO Auto-generated constructor stub  
   }  
     
   @Override  
   protected void onDraw(Canvas canvas) {  
       // TODO Auto-generated method stub  
       super.onDraw(canvas);  
       //初始化Paint  
       Paint paint = new Paint();  
       paint.setColor(Color.RED);  
       paint.setStyle(Style.FILL);  
       paint.setStrokeWidth(2);  
       //构造一个椭圆路径  
       Path ovalPath = new Path();  
       RectF rect =  new RectF(50, 50, 200, 500);    
       ovalPath.addOval(rect, Direction.CCW);  
       //SetPath时,传入一个比椭圆区域小的矩形区域,让其取交集  
       Region rgn = new Region();  
       rgn.setPath(ovalPath,new  Region(50, 50, 200, 200));  
       //画出路径  
       drawRegion(canvas, rgn, paint);  
   }  
     
   //把图形分成矩形,逐个显示
   private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
   {  
       RegionIterator iter = new RegionIterator(rgn);  
       Rect r = new Rect();  
         
       while (iter.next(r)) {  
         canvas.drawRect(r, paint);  
       }   
   }  
}  
Paste_Image.png

5、区域的合并、交叉等操作

无论是区域还是矩形,都会涉及到与另一个区域的一些操作,比如取交集、取并集等,涉及到的函数有:

  • 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)

除了Union(Rect r)是指定合并操作以外,其它四个op()构造函数,都是指定与另一个区域的操作。其中最重要的指定Op的参数,Op的参数有下面四个:

假设用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的区域    
 }   
两个Region 的组合
 @Override  
    protected void onDraw(Canvas canvas) {   
        super.onDraw(canvas);  
         
      
         
         //构造两个矩形  
        Rect rect1 = new Rect(100,100,400,200);  
        Rect rect2 = new Rect(200,0,300,300);  

      //构造一个画笔,画出矩形轮廓  
        Paint paint = new Paint();  
        paint.setColor(Color.RED);  
        paint.setStyle(Style.STROKE);  
        paint.setStrokeWidth(2);  
          
        canvas.drawRect(rect1, paint);  
        canvas.drawRect(rect2, paint);  
          
        //构造两个Region  
        Region region = new Region(rect1);  
        Region region2= new Region(rect2);  
  
        //取两个区域的交集        
        region.op(region2, Op.INTERSECT);  
          
        //再构造一个画笔,填充Region操作结果  
        Paint paint_fill = new Paint();  
        paint_fill.setColor(Color.GREEN);  
        paint_fill.setStyle(Style.FILL);  
        drawRegion(canvas, region, paint_fill);  
  
    }  
      
  
private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
{  
    RegionIterator iter = new RegionIterator(rgn);  
    Rect r = new Rect();  
      
    while (iter.next(r)) {  
      canvas.drawRect(r, paint);  
    }   
}  
Paste_Image.png

6、常用方法

/**几个判断方法*/    
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 
Region.png

参考资料
自定义控件之绘图篇(三):区域(Range)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容