自定义控件之绘图篇(三):区域(Range)
转自:http://blog.csdn.net/harvic880925/article/details/39056701
前言:最近几天对画图的研究有些缓慢,项目开始写代码了,只能在晚上空闲的时候捯饬一下自己的东西,今天给大家讲讲区域的相关知识,已经想好后面两篇的内容了,这几天有时间赶紧写出来给大家。有关界面开发的东东内容确实比较多,慢慢来吧,总有一天会不一样。
我自己的一句警言,送给大家:
想要跟别人不一样,你就要跟别人不一样。—– Harvic
相关文章:
《Android自定义控件三部曲文章索引》: http://blog.csdn.net/harvic880925/article/details/50995268
一、构造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),只知道它可以画出指定的区域就可以了,具体里面是什么意思,后面我们再仔细讲。
- 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 = new Paint();
- paint.setColor(Color.RED);
- paint.setStyle(Style.FILL);
- paint.setStrokeWidth(2);
- Region rgn = new Region(10,10,100,100);
- // rgn.set(100, 100, 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);
- }
- }
- }
public class MyRegionView extends View {public MyRegionView(Context context) {super(context);// TODO Auto-generated constructor stub}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);//初始化画笔Paint paint = new Paint();paint.setColor(Color.RED);paint.setStyle(Style.FILL);paint.setStrokeWidth(2);Region rgn = new Region(10,10,100,100);// rgn.set(100, 100, 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);} }}
看下效果:
未开启Set函数时
使用Set函数后,替换为新区域
3、使用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);
- }
- }
- }
public class MyRegionView extends View {public MyRegionView(Context context) {super(context);// TODO Auto-generated constructor stub}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);//初始化PaintPaint 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);} }
}
结果如下:
二、矩形集枚举区域——RegionIterator类
对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;
RegionIterator(Region region) //根据区域构建对应的矩形集
boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中
由于在Canvas中没有直接绘制Region的函数,我们想要绘制一个区域,就只能通过利用RegionIterator构造矩形集来逼近的显示区域。用法如下:
- 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);
- }
- }
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,重新绘制椭圆路径,会看得更清楚。
三、区域的合并、交叉等操作
无论是区域还是矩形,都会涉及到与另一个区域的一些操作,比如取交集、取并集等,涉及到的函数有:
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的区域
- }
假设用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的区域 }
至于这六个参数的具体意义,后面给个具体的图给大家显示出来,先举个取交集的例子。
效果图:
先构造两个相交叉的矩形,并画出它们的轮廓
- //构造两个矩形
- 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);
//构造两个矩形
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);
然后利用上面的两年rect,(rect1和rect2)来构造区域,并在rect1的基础上取与rect2的交集
- //构造两个Region
- Region region = new Region(rect1);
- Region region2= new Region(rect2);
- //取两个区域的交集
- region.op(region2, Op.INTERSECT);
//构造两个Region
Region region = new Region(rect1);
Region region2= new Region(rect2);//取两个区域的交集
region.op(region2, Op.INTERSECT);
最后构造一个填充画笔,将所选区域用绿色填充起来
- Paint paint_fill = new Paint();
- paint_fill.setColor(Color.GREEN);
- paint_fill.setStyle(Style.FILL);
- drawRegion(canvas, region, paint_fill);
Paint paint_fill = new Paint();
paint_fill.setColor(Color.GREEN);
paint_fill.setStyle(Style.FILL);
drawRegion(canvas, region, paint_fill);
全部代码为:
- /**
- * created by harvic
- * 2014/9/4
- */
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.graphics.Region;
- import android.graphics.Paint.Style;
- import android.graphics.Region.Op;
- import android.graphics.RegionIterator;
- import android.view.View;
- 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);
- //构造两个矩形
- 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);
- }
- }
- }
/*** created by harvic* 2014/9/4*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Paint.Style;
import android.graphics.Region.Op;
import android.graphics.RegionIterator;
import android.view.View;public class MyRegionView extends View {public MyRegionView(Context context) {super(context);// TODO Auto-generated constructor stub}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.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);//构造两个RegionRegion 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);}
}
}
其它参数的操作与这个类似,其实只需要改动region.op(region2, Op.INTERSECT);的Op参数值即可,下面就不再一一列举,给出操作后的对比图。
四、其它一些方法
Region类除了上面的一些重要的方法以外,还有一些比较容易理解的方法,我就不再一一列举用法了,下面一并列出给大家
- /**几个判断方法*/
- 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
/**几个判断方法*/
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
参考文章:《Android 2D Graphics学习(二)、Canvas篇2、Canvas裁剪和Region、RegionIterator》
本篇所涉及到的代码,我集合在了一个工程中,大家可以下载
源码下载地址:http://download.csdn.net/detail/harvic880925/7866523
请大家尊重原创者版权,转载请标时出处:http://blog.csdn.net/harvic880925/article/details/39056701 谢谢!
自定义控件之绘图篇(三):区域(Range)相关推荐
- 自定义控件之绘图篇( 五):drawText()详解
前言:但行好事,莫问前程.只需努力每一天. 相关文章: <Android自定义控件三部曲文章索引>: http://blog.csdn.net/harvic880925/article/ ...
- 自定义控件之绘图篇(二):路径及文字
前言:今天项目进入攻关期,他们改Bug要改疯掉了,主管为了激励大家,给大家发了一封邮件,讲到他对项目和学习的理解,一个很好的图形模型,分享给大家,如图在下面给出:(不便给出原文,我仅做转述) 无论是学 ...
- 自定义控件之绘图篇(一):概述及基本几何图形绘制
转自:http://blog.csdn.net/harvic880925/article/details/38875149 相关文章: <Android自定义控件三部曲文章索引>:http ...
- 自定义view绘图篇--图片和文字的绘制
图片的绘制功能可以让我们直接添加一张图片到画布,文字的绘制可以点缀我们view的功能.本章节继续深入,总结下其中的流程. 知识点 一.绘制图片 1.Picture类 (1)Picture类的功能 我们 ...
- 自定义控件三部曲之绘图篇(十八)——BitmapShader与望远镜效果
上篇初步给大家展示了封装控件的方法,这篇我们继续Paint来看相关方法的用法,这篇我们将会讲一个很起来没啥用,但效果却很屌的方法setShader,这篇文章最后,我们将实现的效果是望远镜效果:(看起来 ...
- ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇
第三章 为控件添加事件 后篇 前一篇文章只是简单的说了下事件,但是大家应该方法,在ASP.NET自定义控件中只是简单那么定义事件是行不 通.如果大家开发的是WinForm中的事件,之前的定义可能没有什 ...
- [Qt教程] 第13篇 2D绘图(三)绘制文字
[Qt教程] 第13篇 2D绘图(三)绘制文字 楼主 发表于 2013-4-25 23:04:46 | 查看: 720| 回复: 0 绘制文字 版权声明 该文章原创于Qter开源社区,作者yafei ...
- ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇
第三章 为控件添加事件 好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件. 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.N ...
- 量化投资常用技能——绘图篇 2:绘制移动平均线
量化投资常用技能--绘图篇 2 前言 移动平均线 使用numpy库计算移动平均值 量化投资第三方库:abupy 欢迎大家关注我们 我们的抖音号:金融观察(JRGC8888) 前言 上一篇文章" ...
最新文章
- NETGEAR拒绝连接请求_3分钟理解HTTP的请求与响应
- 机器学习week3课后作业
- R语言:plot()函数参数合集
- java 最少使用(lru)置换算法_一篇文章学会如何基于LRU-K算法设计本地缓存实现流量削峰...
- dos下清除登录共享用户名和密码
- 计算机专业论文设计与实现,计算机专业论文 计算机网络的设计与实现.doc
- Elasticsearch 数据搜索篇
- 怎样让git不用每次输入密码_不用输入WIFI密码 “一碰连”就能上网
- npm ERR! code EINTEGRITY 解决方案
- 福利工具,如何利用小程序免费下载积分文件呢?【第02期】
- c语言代码怎么转成java,急C语言代码转成java代码,该如何解决
- 大学毕业生推荐表的计算机水平,大学毕业生就业推荐表学校鉴定评语
- TI PMP解决方案简介
- 计算机软件的卸载,电脑里那些软件是不需要的?应该怎么卸载?
- 猎头如何做大单,赚大钱?
- 1062 最简分数 (20 分)
- G001-181-08
- 【Axure基础教程】第19章 树节点
- nodejs获取当前日期
- Python笔记之用turtle库绘制三角函数和反三角函数的图像(考研党福利)
热门文章
- 捋一捋20201217
- Ubuntu18.04安装opencv出现的一系列问题解决方法(持续更新~)
- python实现微信小游戏打飞机代码
- day9 java的静态代码块和代码执行顺序
- mongodb统计函数
- stm32正交编码器 原理图_ROS机器人平台STM32底层控制部分
- android 自定义域名,Android基于Retrofit2改造的可设置多域名的网络加载框架
- db2插入的时候怎么自增_3篇长文讲“自增ID”,大部分人仍然搞错了!?
- 计算机系应用,近距离看专业 计算机专业应用篇
- mysql filck_顺序全局id生成方案-flickr(转载)