自定义View学习④区域(Range)

一、构造Region

基本构造函数
public Region()//创建一个空区域
public Region(Region region)//拷贝一个region范围
public Region(Rect r)//创建一个矩形的区域
public Region(int left, int top, int right, int bottom) //创建一个矩形的区域
参数:
上面的四个构造函数,第一个还要配合其它函数使用,暂时不提。
第二个构造函数是通过其它的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)//后面单独讲
注意:无论调用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系列函数的替换概念
下面写了一个函数,先把Set函数注释起来,看看画出来的区域的位置,然后开启Set函数,然后再看画出来的区域
注:里面有个函数drawRegion(Canvas canvas,Region rgn,Paint paint),只知道它可以画出指定的区域就可以了,具体里面是什么意思,后面我们再仔细讲。(我也不懂。。跟着实现了一下,是可以看到效果)

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化画笔
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        Region region = new Region(10, 10, 100, 100);
//        region.set(100, 100, 200, 200);
        drawRegion(canvas, paint, region);
    }

    private void drawRegion(Canvas canvas, Paint paint, Region region) {
    ·	//这边是真不懂。。
        RegionIterator iterator = new RegionIterator(region);
        Rect rect = new Rect();
        while (iterator.next(rect)) {
            canvas.drawRect(rect, paint);
        }
    }

效果图 —》未开启:
自定义View学习④区域(Range)_第1张图片

开启 – 》:
自定义View学习④区域(Range)_第2张图片
说明是有效果的。。。可以替换
使用SetPath()构造不规则区域
boolean setPath (Path path, Region clip)
参数说明:
Path path:用来构造的区域的路径
Region clip:与前面的path所构成的路径取交集,并将两交集设置为最终的区域
由于路径有很多种构造方法,而且可以轻意构造出非矩形的路径,这就摆脱了前面的构造函数只能构造矩形区域的限制。但这里有个问题是要指定另一个区域来取共同的交集,当然如果想显示路径构造的区域,Region clip参数可以传一个比Path范围大的多的区域,取完交集之后,当然是Path参数所对应的区域喽。

代码:

	@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化画笔
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);

        //构造一个椭圆路径
        Path ovalPath = new Path();
        RectF rectF = new RectF(50, 50, 200, 500);
        ovalPath.addOval(rectF, Path.Direction.CCW);

        //在setPath时,传入一个比椭圆区域小的矩形区域,让其取交集
        Region region = new Region();
        region.setPath(ovalPath, new Region(50, 50, 200, 200));
        //画出路径
        drawRegion(canvas, paint, region);
    }

    private void drawRegion(Canvas canvas, Paint paint, Region region) {
        RegionIterator iter = new RegionIterator(region);
        Rect r = new Rect();

        while (iter.next(r)) {
            canvas.drawRect(r, paint);
        }

效果图 ----》略懂吧。。:
自定义View学习④区域(Range)_第3张图片

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

下面就是对drawRegion()这个方法的具体讲解。
对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。(就像像素游戏,很多块像素然后组合成一个形状)RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;
RegionIterator(Region region) //根据区域构建对应的矩形集
boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中
由于在Canvas中没有直接绘制Region的函数,我们想要绘制一个区域,就只能通过利用RegionIterator构造矩形集来逼近的显示区域。用法如下:

    private void drawRegion(Canvas canvas, Paint paint, Region region) {
        RegionIterator iter = new RegionIterator(region);
        Rect r = new Rect();

        while (iter.next(r)) {
            canvas.drawRect(r, paint);
        }
    }

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

效果图:
自定义View学习④区域(Range)_第4张图片

区域的合并、交叉等操作

无论是区域还是矩形,都会涉及到与另一个区域的一些操作,比如取交集、取并集等(就像初中的数学题去交集并集啥的),涉及到的函数有:
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)

假设用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的区域  
 }

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

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化画笔
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);

        //构造两个矩形
        Rect rect1 = new Rect(100,100,400,200);
        Rect rect2 = new Rect(200,0,300,300);
        canvas.drawRect(rect1, paint);
        canvas.drawRect(rect2, paint);
//        drawRegion(canvas, paint, region);
    }

效果图:
自定义View学习④区域(Range)_第5张图片
然后利用上面的两个rect,(rect1和rect2)来构造区域,并在rect1的基础上取与rect2的交集

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //初始化画笔
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);

        //构造两个矩形
        Rect rect1 = new Rect(100, 100, 400, 200);
        Rect rect2 = new Rect(200, 0, 300, 300);
        canvas.drawRect(rect1, paint);
        canvas.drawRect(rect2, paint);

        Region region = new Region(rect1);
        Region region1 = new Region(rect2);
        region.op(region1, Region.Op.INTERSECT);
        //最后构造一个填充画笔,将所选区域用绿色填充起来'
        Paint paint1 = new Paint();
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        //画出来
        drawRegion(canvas, paint, region);
    }

    private void drawRegion(Canvas canvas, Paint paint, Region region) {
        RegionIterator iter = new RegionIterator(region);
        Rect r = new Rect();

        while (iter.next(r)) {
            canvas.drawRect(r, paint);
        }

    }

效果图:
自定义View学习④区域(Range)_第6张图片
其他效果 – 》后面注明摘自哪里:
自定义View学习④区域(Range)_第7张图片

其它一些方法

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

学到这里,还是不太知道区域在实际开发中的作用
学习文章:自定义控件之绘图篇(三):区域(Range)

你可能感兴趣的:(Android)