zoukankan      html  css  js  c++  java
  • android Graphics(三):区域(Range)

    前言:最近几天对画图的研究有些缓慢,项目开始写代码了,只能在晚上空闲的时候捯饬一下自己的东西,今天给大家讲讲区域的相关知识,已经想好后面两篇的内容了,这几天有时间赶紧写出来给大家。有关界面开发的东东内容确实比较多,慢慢来吧,总有一天会不一样。

     

    我自己的一句警言,送给大家:

    想要跟别人不一样,你就要跟别人不一样。----- Harvic 

     

     

    相关文章:

    1、《android Graphics(一):概述及基本几何图形绘制》
    2、《android Graphics(二):路径及文字》
    3、《android Graphics(三):区域(Range)》
    4、《android Graphics(四):canvas变换与操作》

    一、构造Region

    1、基本构造函数

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

    上面的四个构造函数,第一个还要配合其它函数使用,暂时不提。
    第二个构造函数是通过其它的Region来复制一个同样的Region变量
    第三个,第四个才是正规常的,根据一个矩形或矩形的左上角和右下角点构造出一个矩形区域

    2、间接构造

     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):根据路径的区域与某区域的交集,构造出新区域,这个后面具体讲解

    举个小例子,来说明一个Set系列函数的替换概念:

    关于重写新建一个类,并派生自view,并且要重写OnDraw函数的问题我就不再讲了,有问题的同学,可以参考下《android Graphics(一):概述及基本几何图形绘制》,当然最后我也会给出相关的源码,直接看源码也行。

    下面写了一个函数,先把Set函数注释起来,看看画出来的区域的位置,然后开启Set函数,然后再看画出来的区域
    注:里面有个函数drawRegion(Canvas canvas,Region rgn,Paint paint),只知道它可以画出指定的区域就可以了,具体里面是什么意思,后面我们再仔细讲。

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class MyRegionView extends View {  
    2.   
    3.     public MyRegionView(Context context) {  
    4.         super(context);  
    5.         // TODO Auto-generated constructor stub  
    6.     }  
    7.       
    8.     @Override  
    9.     protected void onDraw(Canvas canvas) {  
    10.         // TODO Auto-generated method stub  
    11.         super.onDraw(canvas);  
    12.           
    13.         //初始化画笔  
    14.         Paint paint = new Paint();  
    15.         paint.setColor(Color.RED);  
    16.         paint.setStyle(Style.FILL);  
    17.         paint.setStrokeWidth(2);  
    18.           
    19.         Region rgn = new Region(10,10,100,100);  
    20.   
    21. //      rgn.set(100, 100, 200, 200);  
    22.         drawRegion(canvas, rgn, paint);  
    23.           
    24.     }  
    25.       
    26.     //这个函数不懂没关系,下面会细讲  
    27.     private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    28.     {  
    29.         RegionIterator iter = new RegionIterator(rgn);  
    30.         Rect r = new Rect();  
    31.           
    32.         while (iter.next(r)) {  
    33.           canvas.drawRect(r, paint);  
    34.         }   
    35.     }  
    36.   
    37. }  

    看下效果:
                                未开启Set函数时                                                                                           

                           使用Set函数后,替换为新区域

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

    boolean setPath (Path path, Region clip)

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

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

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

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class MyRegionView extends View {  
    2.   
    3.     public MyRegionView(Context context) {  
    4.         super(context);  
    5.         // TODO Auto-generated constructor stub  
    6.     }  
    7.       
    8.     @Override  
    9.     protected void onDraw(Canvas canvas) {  
    10.         // TODO Auto-generated method stub  
    11.         super.onDraw(canvas);  
    12.         //初始化Paint  
    13.         Paint paint = new Paint();  
    14.         paint.setColor(Color.RED);  
    15.         paint.setStyle(Style.FILL);  
    16.         paint.setStrokeWidth(2);  
    17.         //构造一个椭圆路径  
    18.         Path ovalPath = new Path();  
    19.         RectF rect =  new RectF(50, 50, 200, 500);    
    20.         ovalPath.addOval(rect, Direction.CCW);  
    21.         //SetPath时,传入一个比椭圆区域小的矩形区域,让其取交集  
    22.         Region rgn = new Region();  
    23.         rgn.setPath(ovalPath,new  Region(50, 50, 200, 200));  
    24.         //画出路径  
    25.         drawRegion(canvas, rgn, paint);  
    26.     }  
    27.       
    28.     //这个函数不懂没关系,下面会细讲  
    29.     private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    30.     {  
    31.         RegionIterator iter = new RegionIterator(rgn);  
    32.         Rect r = new Rect();  
    33.           
    34.         while (iter.next(r)) {  
    35.           canvas.drawRect(r, paint);  
    36.         }   
    37.     }  
    38. }  

    结果如下:

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

    对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;
    RegionIterator(Region region) //根据区域构建对应的矩形集
    boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中

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

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    2. {  
    3.     RegionIterator iter = new RegionIterator(rgn);  
    4.     Rect r = new Rect();  
    5.       
    6.     while (iter.next(r)) {  
    7.       canvas.drawRect(r, paint);  
    8.     }   
    9. }  

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

     

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

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

    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的参数有下面四个:

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    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.  }   

    至于这六个参数的具体意义,后面给个具体的图给大家显示出来,先举个取交集的例子。

    效果图:

    先构造两个相交叉的矩形,并画出它们的轮廓

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //构造两个矩形  
    2. Rect rect1 = new Rect(100,100,400,200);  
    3. Rect rect2 = new Rect(200,0,300,300);  
    4.   
    5. //构造一个画笔,画出矩形轮廓  
    6. Paint paint = new Paint();  
    7. paint.setColor(Color.RED);  
    8. paint.setStyle(Style.STROKE);  
    9. paint.setStrokeWidth(2);  
    10.   
    11. canvas.drawRect(rect1, paint);  
    12. canvas.drawRect(rect2, paint);  

    然后利用上面的两年rect,(rect1和rect2)来构造区域,并在rect1的基础上取与rect2的交集

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. //构造两个Region  
    2. Region region = new Region(rect1);  
    3. Region region2= new Region(rect2);  
    4.   
    5. //取两个区域的交集        
    6. region.op(region2, Op.INTERSECT);  

    最后构造一个填充画笔,将所选区域用绿色填充起来

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. Paint paint_fill = new Paint();  
    2. paint_fill.setColor(Color.GREEN);  
    3. paint_fill.setStyle(Style.FILL);  
    4. drawRegion(canvas, region, paint_fill);  

    全部代码为:

     

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /** 
    2.  * created by harvic 
    3.  * 2014/9/4 
    4.  */  
    5. import android.content.Context;  
    6. import android.graphics.Canvas;  
    7. import android.graphics.Color;  
    8. import android.graphics.Paint;  
    9. import android.graphics.Rect;  
    10. import android.graphics.Region;  
    11. import android.graphics.Paint.Style;  
    12. import android.graphics.Region.Op;  
    13. import android.graphics.RegionIterator;  
    14. import android.view.View;  
    15.   
    16. public class MyRegionView extends View {  
    17.   
    18.     public MyRegionView(Context context) {  
    19.         super(context);  
    20.         // TODO Auto-generated constructor stub  
    21.     }  
    22.       
    23.     @Override  
    24.     protected void onDraw(Canvas canvas) {  
    25.         // TODO Auto-generated method stub  
    26.         super.onDraw(canvas);  
    27.           
    28.         //构造两个矩形  
    29.         Rect rect1 = new Rect(100,100,400,200);  
    30.         Rect rect2 = new Rect(200,0,300,300);  
    31.           
    32.         //构造一个画笔,画出矩形轮廓  
    33.         Paint paint = new Paint();  
    34.         paint.setColor(Color.RED);  
    35.         paint.setStyle(Style.STROKE);  
    36.         paint.setStrokeWidth(2);  
    37.           
    38.         canvas.drawRect(rect1, paint);  
    39.         canvas.drawRect(rect2, paint);  
    40.           
    41.           
    42.           
    43.         //构造两个Region  
    44.         Region region = new Region(rect1);  
    45.         Region region2= new Region(rect2);  
    46.   
    47.         //取两个区域的交集        
    48.         region.op(region2, Op.INTERSECT);  
    49.           
    50.         //再构造一个画笔,填充Region操作结果  
    51.         Paint paint_fill = new Paint();  
    52.         paint_fill.setColor(Color.GREEN);  
    53.         paint_fill.setStyle(Style.FILL);  
    54.         drawRegion(canvas, region, paint_fill);  
    55.   
    56.     }  
    57.       
    58.   
    59. private void drawRegion(Canvas canvas,Region rgn,Paint paint)  
    60. {  
    61.     RegionIterator iter = new RegionIterator(rgn);  
    62.     Rect r = new Rect();  
    63.       
    64.     while (iter.next(r)) {  
    65.       canvas.drawRect(r, paint);  
    66.     }   
    67. }  
    68. }  

    其它参数的操作与这个类似,其实只需要改动region.op(region2, Op.INTERSECT);的Op参数值即可,下面就不再一一列举,给出操作后的对比图。


    四、其它一些方法

    Region类除了上面的一些重要的方法以外,还有一些比较容易理解的方法,我就不再一一列举用法了,下面一并列出给大家

     

    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /**几个判断方法*/    
    2. public native boolean isEmpty();//判断该区域是否为空    
    3. public native boolean isRect(); //是否是一个矩阵    
    4. public native boolean isComplex();//是否是多个矩阵组合    
    5.     
    6.     
    7. /**一系列的getBound方法,返回一个Region的边界*/    
    8. public Rect getBounds()     
    9. public boolean getBounds(Rect r)     
    10. public Path getBoundaryPath()     
    11. public boolean getBoundaryPath(Path path)     
    12.     
    13.     
    14. /**一系列的判断是否包含某点 和是否相交*/    
    15. public native boolean contains(int x, int y);//是否包含某点    
    16. public boolean quickContains(Rect r)   //是否包含某矩阵    
    17. public native boolean quickContains(int left, int top, int right,    
    18.                                         int bottom) //是否没有包含某矩阵    
    19.  public boolean quickReject(Rect r) //是否没和该矩阵相交    
    20.  public native boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩阵相交    
    21.  public native boolean quickReject(Region rgn);  //是否没和该矩阵相交    
    22.     
    23. /**几个平移变换的方法*/    
    24. public void translate(int dx, int dy)     
    25. public native void translate(int dx, int dy, Region dst);    
    26. public void scale(float scale) //hide    
    27. public native void scale(float scale, Region dst);//hide    

    参考文章:《Android 2D Graphics学习(二)、Canvas篇2、Canvas裁剪和Region、RegionIterator》

     

    本篇所涉及到的代码,我集合在了一个工程中,大家可以下载

    源码下载地址:http://download.csdn.net/detail/harvic880925/7866523

    请大家尊重原创者版权,转载请标时出处:http://blog.csdn.net/harvic880925/article/details/39056701   谢谢!

  • 相关阅读:
    数据建模学习笔记-1-《高质量数据库建模 1-重大意义》
    sqoop中,如果数据中本身有换行符,会导致数据错位
    telnet时显示:允许更多到 telnet 服务器的连接。请稍候再试
    Eclipse首字母快捷设置
    error: bad symbolic reference. A signature in HiveContext.class refers to term hive
    在IT的路上,我在成长
    uglifyjs-webpack-plugin 插件,drop_console 默认为 false(不清除 console 语句),drop_debugger 默认为 true(清除 debugger 语句)
    读《精通正则表达式(第三版)》笔记
    vue cli 3.x 设置4个空格缩进
    正则表达式 学习资料
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4507627.html
Copyright © 2011-2022 走看看