《Android自定义控件入门到精通》文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683

《Android自定义控件入门到精通》所有源码 ☞ https://gitee.com/zengjiangwen/Code

文章目录

  • Region
    • Region.set()
    • Region.get()
      • getBounds()
      • Region.getBoundaryPath()
    • Region.op()
      • op(Region ,Op)
      • op(Region,Region,Op)
    • Region的其它方法

Region

Region(区域),跟Rect(矩形)类似也有很大不同,一个Region是由一个或多个Rect组成

Region构造:

  • Region() 构造一个空的区域
  • Region(Region) 根据现有的区域构造新的区域,等于复制一个一样的
  • Region(Rect) 根据一个矩形构造一个区域
  • Region(left,top,right,bottom) 通过四个边界确定一个区域
@Override
protected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(Color.RED);Region region=new Region(10,10,100,120);drawRegion(region,canvas,mPaint);
}private void drawRegion(Region region,Canvas canvas,Paint paint){RegionIterator iterator=new RegionIterator(region);Rect rect=new Rect();while (iterator.next(rect)){//遍历canvas.drawRect(rect,paint);}
}

Canvas并没有直接canvas.drawRegion的方法,但是提供了RegionIterator类,可以自己实现一个drawRegion()方法,由于这个Region是通过一个Rect构成的,所以画出来跟Rect是一样的。

如果Region不是矩形,那会是什么样子呢?

    @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.RED);//创建一个空的RegionRegion region = new Region();//通过path创建一个椭圆Path path = new Path();path.addOval(10, 10, 160, 320, Path.Direction.CW);//将椭圆添加到空的Region,并通过新的Region进行裁剪region.setPath(path, new Region(10, 10, 160, 160));drawRegion(region, canvas, mPaint);}

通过上面的例子我们可以清楚的明白,一个Region是有一个或者多个Rect组成。

Region.set()

前三个就是设置Region的区域了,没啥说的

setPath上面讲过了,可以理解为一个裁剪功能

setEmpty为置空/清空区域内容

Region.get()

getBounds()

返回Region的区域范围,通过上面Region椭圆的例子我们猜测,Region的边界到底是整个椭圆所在矩形还是椭圆的上半部分所在矩形区域,setPath()裁剪后,Region的区域怎么确定

    @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.RED);//创建一个空的RegionRegion region = new Region();//通过path创建一个椭圆Path path = new Path();path.addOval(10, 10, 160, 320, Path.Direction.CW);//将椭圆添加到空的Region,并通过新的Region进行裁剪,也可以理解为在新的Region中呈现region.setPath(path, new Region(10, 10, 160, 160));drawRegion(region, canvas, mPaint);//画出椭圆的区域mPaint.setColor(Color.BLUE);canvas.drawPath(path, mPaint);//画出region的区域mPaint.setColor(Color.YELLOW);Rect rect = region.getBounds();canvas.drawRect(rect, mPaint);}

黄色框为Region.getBounds()的区域,也就是setPath的第二个参数new Region(10,10,160,160)的范围

Region.getBoundaryPath()

    @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.RED);//创建一个空的RegionRegion region = new Region();//通过path创建一个椭圆Path path = new Path();path.addOval(10, 10, 160, 320, Path.Direction.CW);//将椭圆添加到空的Region,并通过新的Region进行裁剪,也可以理解为在新的Region中呈现region.setPath(path, new Region(10, 10, 160, 160));drawRegion(region, canvas, mPaint);//画出椭圆的区域mPaint.setColor(Color.BLUE);canvas.drawPath(path, mPaint);//画出region的区域mPaint.setColor(Color.YELLOW);Path boundaryPath = region.getBoundaryPath();canvas.drawPath(boundaryPath, mPaint);}

啥,这是个啥?什么也没有啊!

Region.getBoundaryPath()顾名思义呢是返回Region区域图形的Path路径,那应该就是椭圆的上半部分的Path啊,怎么没有呢?

注意了,Region.getBoundaryPath()只是获取的Path只有原始数据,Path是路劲概念,不能直接Draw出来,需要转换一下

    @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.RED);//创建一个空的RegionRegion region = new Region();//通过path创建一个椭圆Path path = new Path();path.addOval(10, 10, 160, 320, Path.Direction.CW);//将椭圆添加到空的Region,并通过新的Region进行裁剪,也可以理解为在新的Region中呈现region.setPath(path, new Region(10, 10, 160, 160));drawRegion(region, canvas, mPaint);//画出椭圆的区域mPaint.setColor(Color.BLUE);canvas.drawPath(path, mPaint);//画出region的区域mPaint.setColor(Color.YELLOW);Path boundaryPath = region.getBoundaryPath();boundaryPath.transform(new Matrix());canvas.drawPath(boundaryPath, mPaint);}

黄色路径就是Region内部元素的Path了,同样的,我们还可以通过Matrix来操作这个Path

    @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(Color.RED);//创建一个空的RegionRegion region = new Region();//通过path创建一个椭圆Path path = new Path();path.addOval(10, 10, 160, 320, Path.Direction.CW);//将椭圆添加到空的Region,并通过新的Region进行裁剪,也可以理解为在新的Region中呈现region.setPath(path, new Region(10, 10, 160, 160));drawRegion(region, canvas, mPaint);//画出椭圆的区域mPaint.setColor(Color.BLUE);canvas.drawPath(path, mPaint);//画出region的区域mPaint.setColor(Color.YELLOW);Path boundaryPath= region.getBoundaryPath();Matrix matrix=new Matrix();//向右平移100matrix.setTranslate(100,0);boundaryPath.transform(matrix);canvas.drawPath(boundaryPath,mPaint);}

Region.op()

op()是对Region的混合操作,我们知道,两个区域可以相交,那就有交集,并集,补集等概念。

图形的Op有以下几种:

    public enum Op {DIFFERENCE(0),INTERSECT(1),UNION(2),XOR(3),REVERSE_DIFFERENCE(4),REPLACE(5);}

op(Region ,Op)

 @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(Color.GRAY);//第一组RegionRegion regionOneAndOne = new Region(20, 50, 120, 90);Region regionOneAndTwo = new Region(50, 20, 90, 120);//第二组RegionRegion regionTwoAndOne = new Region(160, 50, 260, 90);Region regionTwoAndTwo = new Region(190, 20, 230, 120);//第三组RegionRegion regionThreeAndOne = new Region(300, 50, 400, 90);Region regionThreeAndTwo = new Region(330, 20, 370, 120);//第四组RegionRegion regionFourAndOne = new Region(20, 190, 120, 230);Region regionFourAndTwo = new Region(50, 160, 90, 260);//第五组RegionRegion regionFiveAndOne = new Region(160, 190, 260, 230);Region regionFiveAndTwo = new Region(190, 160, 230, 260);//第六组RegionRegion regionSixAndOne = new Region(300, 190, 400, 230);Region regionSixAndTwo = new Region(330, 160, 370, 260);drawRegion(regionOneAndOne, canvas, mPaint);drawRegion(regionOneAndTwo, canvas, mPaint);drawRegion(regionTwoAndOne, canvas, mPaint);drawRegion(regionTwoAndTwo, canvas, mPaint);drawRegion(regionThreeAndOne, canvas, mPaint);drawRegion(regionThreeAndTwo, canvas, mPaint);drawRegion(regionFourAndOne, canvas, mPaint);drawRegion(regionFourAndTwo, canvas, mPaint);drawRegion(regionFiveAndOne, canvas, mPaint);drawRegion(regionFiveAndTwo, canvas, mPaint);drawRegion(regionSixAndOne, canvas, mPaint);drawRegion(regionSixAndTwo, canvas, mPaint);mPaint.setColor(Color.YELLOW);regionOneAndOne.op(regionOneAndTwo, Region.Op.DIFFERENCE);//op操作之后的区域保存在regionOneAndOnedrawRegion(regionOneAndOne, canvas, mPaint);canvas.drawText("Op.DIFFERENCE", 30, 140, mPaint);regionTwoAndOne.op(regionTwoAndTwo, Region.Op.INTERSECT);drawRegion(regionTwoAndOne, canvas, mPaint);canvas.drawText("Op.INTERSECT", 170, 140, mPaint);regionThreeAndOne.op(regionThreeAndTwo, Region.Op.UNION);drawRegion(regionThreeAndOne, canvas, mPaint);canvas.drawText("Op.UNION", 320, 140, mPaint);regionFourAndOne.op(regionFourAndTwo, Region.Op.XOR);drawRegion(regionFourAndOne, canvas, mPaint);canvas.drawText("Op.XOR", 50, 280, mPaint);regionFiveAndOne.op(regionFiveAndTwo, Region.Op.REPLACE);drawRegion(regionFiveAndOne, canvas, mPaint);canvas.drawText("Op.REPLACE", 175, 280, mPaint);regionSixAndOne.op(regionSixAndTwo, Region.Op.REVERSE_DIFFERENCE);drawRegion(regionSixAndOne, canvas, mPaint);canvas.drawText("Op.REVERSE_DIFFERENCE", 280, 280, mPaint);}

op(Region,Region,Op)

这里参数中有两个Region,包括调用者,一共有三个Region参与Op操作?

我们先实现三个Op类型,再在改变这三个Op类型就可以实现六组类型了

我们通过红、绿、蓝三个圆形区域相交来说明 op(Region,Region,Op),并且还是用黄色来绘制最终的op结果

 @Overrideprotected void onDraw(Canvas canvas) {mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(Color.GRAY);//第一组RegionRegion regionOneAndOne = new Region();Path path11 = new Path();path11.addCircle(90, 60, 40, Path.Direction.CW);regionOneAndOne.setPath(path11, new Region(50, 20, 130, 100));mPaint.setColor(Color.RED);drawRegion(regionOneAndOne, canvas, mPaint);Region regionOneAndTwo = new Region();Path path12 = new Path();path12.addCircle(60, 90, 40, Path.Direction.CW);regionOneAndTwo.setPath(path12, new Region(20, 50, 100, 130));mPaint.setColor(Color.GREEN);drawRegion(regionOneAndTwo, canvas, mPaint);Region regionOneAndThree = new Region();Path path13 = new Path();path13.addCircle(120, 90, 40, Path.Direction.CW);regionOneAndThree.setPath(path13, new Region(80, 50, 160, 130));mPaint.setColor(Color.BLUE);drawRegion(regionOneAndThree, canvas, mPaint);//第一组OpregionOneAndOne.op(regionOneAndTwo, regionOneAndThree, Region.Op.DIFFERENCE);mPaint.setColor(Color.YELLOW);drawRegion(regionOneAndOne, canvas, mPaint);canvas.drawText("Op.DIFFERENCE", 70, 150, mPaint);//第二组RegionRegion regionTwoAndOne = new Region();Path path21 = new Path();path21.addCircle(270, 60, 40, Path.Direction.CW);regionTwoAndOne.setPath(path21, new Region(230, 20, 310, 100));mPaint.setColor(Color.RED);drawRegion(regionTwoAndOne, canvas, mPaint);Region regionTwoAndTwo = new Region();Path path22 = new Path();path22.addCircle(240, 90, 40, Path.Direction.CW);regionTwoAndTwo.setPath(path22, new Region(200, 50, 280, 130));mPaint.setColor(Color.GREEN);drawRegion(regionTwoAndTwo, canvas, mPaint);Region regionTwoAndThree = new Region();Path path23 = new Path();path23.addCircle(300, 90, 40, Path.Direction.CW);regionTwoAndThree.setPath(path23, new Region(260, 50, 340, 130));mPaint.setColor(Color.BLUE);drawRegion(regionTwoAndThree, canvas, mPaint);//第二组OpregionTwoAndOne.op(regionTwoAndTwo, regionTwoAndThree, Region.Op.INTERSECT);mPaint.setColor(Color.YELLOW);drawRegion(regionTwoAndOne, canvas, mPaint);canvas.drawText("Op.INTERSECT", 250, 150, mPaint);//第三组RegionRegion regionThreeAndOne = new Region();Path path31 = new Path();path31.addCircle(450, 60, 40, Path.Direction.CW);regionThreeAndOne.setPath(path31, new Region(410, 20, 490, 100));mPaint.setColor(Color.RED);drawRegion(regionThreeAndOne, canvas, mPaint);Region regionThreeAndTwo = new Region();Path path32 = new Path();path32.addCircle(420, 90, 40, Path.Direction.CW);regionThreeAndTwo.setPath(path32, new Region(380, 50, 460, 130));mPaint.setColor(Color.GREEN);drawRegion(regionThreeAndTwo, canvas, mPaint);Region regionThreeAndThree = new Region();Path path33 = new Path();path33.addCircle(480, 90, 40, Path.Direction.CW);regionThreeAndThree.setPath(path33, new Region(440, 50, 520, 130));mPaint.setColor(Color.BLUE);drawRegion(regionThreeAndThree, canvas, mPaint);//第三组OpregionThreeAndOne.op(regionThreeAndTwo, regionThreeAndThree, Region.Op.UNION);mPaint.setColor(Color.YELLOW);drawRegion(regionThreeAndOne, canvas, mPaint);canvas.drawText("Op.UNION", 430, 150, mPaint);}

可以看到,红色圆形并没有参与op操作,结果也跟上图一样。

其实通过源码,我们可以发现

region1.op(region2 ,op)=region1.op(region1,region2,op)

同理:

region1.op(region2,region3,op)=region2.op(region3,op)

结论,op操作只针对参数中的两个Region操作,与调用者无关。

Region的其它方法

boolean isEmpty();//判断该区域是否为空
boolean isRect(); //是否是一个矩形
boolean isComplex();//是否是多个区域组合
boolean contains(int x, int y);//是否包含某点
boolean quickContains(Rect r);  //是否包含某矩形
boolean quickContains(int left, int top, int right, int bottom); //是否没有包含某矩形
boolean quickReject(Rect r);//是否没和该矩形相交
boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩形相交
boolean quickReject(Region region);  //是否没和该区域相交
void translate(int dx, int dy);//对区域平移
void translate(int dx, int dy, Region dst);//对区域平移,结果用dst接受,如果dst为空,那么改变的是本身this
void scale(float scale); //对区域放大缩小
void scale(float scale, Region dst);//对区域放大缩小,结果用dst接受,如果dst为空,那么改变的是本身this

Android自定义控件入门到精通--Region区域相关推荐

  1. Android自定义控件入门到精通--View树的布局

    <Android自定义控件入门到精通>文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683 <Andro ...

  2. Android自定义控件入门到精通--View树的测量流程

    <Android自定义控件入门到精通>文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683 <Andro ...

  3. 我的新书《Android自定义控件入门与实战》出版啦

    前言:当你回首往事时,不以虚度年华而悔恨,不以碌碌无为而羞耻,那你就可以骄傲的跟自己讲,你不负此生 [Android自定义控件入门与实战]勘误:https://blog.csdn.net/harvic ...

  4. Android Volley入门到精通:初识Volley的基本用法

    1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...

  5. Android studio入门到精通实例实验

    Android studio入门到精通实例实验 实验内容: ----------------- 简单的考试程序---------------- 实验步骤: 一.打开Android studio,新建一 ...

  6. 《Android从入门到精通》家庭理财通

    闲着没事把<Android从入门到精通>最后的项目给写了.以下是该项目的各文件之间的关联. 我把书上没写的那一部分,就是OutAccount部分代码补齐了(因为书后面的光盘没有了,所以只能 ...

  7. android从入门到精通pdf 明日科技

    android从入门到精通pdf 明日科技 链接: https://pan.baidu.com/s/1dGSkbCl 密码: wpaa (失效) 链接:https://pan.baidu.com/s/ ...

  8. android bsp入门到精通,网管教程:从入门到精通(软件篇).pdf

    网管教程:从入门到精通(软件篇) Ver 1.1 Feihon (609095519 )整理 2010-4-26 (资料来自 IT 网绚技术赸级群癿分享,本人仅提供整理,原作者未知 ) 网管教程:从入 ...

  9. Android自定义控件入门实践之雷达扫描控件

    以前因为工作的关系,对于自定义控件用的少之又少,无非就是把几个控件放置到ViewGroup内部,然后提供开放方法,就成了一个所谓的自定义控件,但是这种小伎俩太简单,面试的时候这点东西根本Hold不住场 ...

最新文章

  1. pyqt怎么给字体加粗_微信拍一拍可设置后缀?怎么用?还有更多新功能!
  2. PRD 的编写和修改注意事项
  3. 《Linux》阿里云部署django全攻略
  4. 多模态AI开发套件HiLens Kit:超强算力彰显云上实力
  5. WPF解析Word为图片
  6. 简单选择排序_Python3三种简单排序(冒泡、插入、选择)的比较
  7. 使用seaborn制图(箱型图)
  8. PyCharm2021设置成中文版
  9. vscode-扩展插件
  10. 简易智能自动问答机器人
  11. RTSP、RTMP、HTTP流媒体播放器比较
  12. java操作zip压缩文件加密码和解密工具类
  13. 中班音乐活动 机器人_中班下学期音乐《机器人》活动反思
  14. python中的内置高阶函数
  15. 我们要注意的问题.net
  16. 李小冉传婚讯 与好友回京拥抱告别
  17. 表面粗糙度的基本评定参数是_表面粗糙度最常用评定参数是什么?
  18. 关于:Windows Server 2008 R2 中的 Hyper-V(旧作)
  19. html中图片链接生成文字,利用HTML5使文字转图片【长微博生成器】
  20. 用SPSS估计HLM多层(层次)线性模型模型

热门文章

  1. 适配USB接口奕力 ILITEK Multi-Touch-V5000
  2. python爬虫--小说爬取
  3. 死亡公司公墓数据(IT桔子)
  4. 老周的ABP框架系列教程
  5. 微信小程序,分享如何封装一个全局支持暂停,拖动等各类操作的音视频等多媒体管理器
  6. video.js 实现视频只能后退,不能快进
  7. 【转】Guide to Elliptic Curve Cryptography(ECC椭圆曲线算法1)
  8. 如何利用爬虫工具实现竞品价格监控
  9. 图书管理系统-成绩管理系统
  10. Python学习笔记(一)——Anaconda安装与配置(windows)