Android自定义控件入门到精通--Region区域
《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区域相关推荐
- Android自定义控件入门到精通--View树的布局
<Android自定义控件入门到精通>文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683 <Andro ...
- Android自定义控件入门到精通--View树的测量流程
<Android自定义控件入门到精通>文章索引 ☞ https://blog.csdn.net/Jhone_csdn/article/details/118146683 <Andro ...
- 我的新书《Android自定义控件入门与实战》出版啦
前言:当你回首往事时,不以虚度年华而悔恨,不以碌碌无为而羞耻,那你就可以骄傲的跟自己讲,你不负此生 [Android自定义控件入门与实战]勘误:https://blog.csdn.net/harvic ...
- Android Volley入门到精通:初识Volley的基本用法
1. Volley简介 我们平时在开发Android应用的时候不可避免地都需要用到网络技术,而多数情况下应用程序都会使用HTTP协议来发送和接收网络数据.Android系统中主要提供了两种方式来进行H ...
- Android studio入门到精通实例实验
Android studio入门到精通实例实验 实验内容: ----------------- 简单的考试程序---------------- 实验步骤: 一.打开Android studio,新建一 ...
- 《Android从入门到精通》家庭理财通
闲着没事把<Android从入门到精通>最后的项目给写了.以下是该项目的各文件之间的关联. 我把书上没写的那一部分,就是OutAccount部分代码补齐了(因为书后面的光盘没有了,所以只能 ...
- android从入门到精通pdf 明日科技
android从入门到精通pdf 明日科技 链接: https://pan.baidu.com/s/1dGSkbCl 密码: wpaa (失效) 链接:https://pan.baidu.com/s/ ...
- android bsp入门到精通,网管教程:从入门到精通(软件篇).pdf
网管教程:从入门到精通(软件篇) Ver 1.1 Feihon (609095519 )整理 2010-4-26 (资料来自 IT 网绚技术赸级群癿分享,本人仅提供整理,原作者未知 ) 网管教程:从入 ...
- Android自定义控件入门实践之雷达扫描控件
以前因为工作的关系,对于自定义控件用的少之又少,无非就是把几个控件放置到ViewGroup内部,然后提供开放方法,就成了一个所谓的自定义控件,但是这种小伎俩太简单,面试的时候这点东西根本Hold不住场 ...
最新文章
- pyqt怎么给字体加粗_微信拍一拍可设置后缀?怎么用?还有更多新功能!
- PRD 的编写和修改注意事项
- 《Linux》阿里云部署django全攻略
- 多模态AI开发套件HiLens Kit:超强算力彰显云上实力
- WPF解析Word为图片
- 简单选择排序_Python3三种简单排序(冒泡、插入、选择)的比较
- 使用seaborn制图(箱型图)
- PyCharm2021设置成中文版
- vscode-扩展插件
- 简易智能自动问答机器人
- RTSP、RTMP、HTTP流媒体播放器比较
- java操作zip压缩文件加密码和解密工具类
- 中班音乐活动 机器人_中班下学期音乐《机器人》活动反思
- python中的内置高阶函数
- 我们要注意的问题.net
- 李小冉传婚讯 与好友回京拥抱告别
- 表面粗糙度的基本评定参数是_表面粗糙度最常用评定参数是什么?
- 关于:Windows Server 2008 R2 中的 Hyper-V(旧作)
- html中图片链接生成文字,利用HTML5使文字转图片【长微博生成器】
- 用SPSS估计HLM多层(层次)线性模型模型