区域代表画布中的一块封闭区域,可用于扩大点击范围或者设定不规则的点击范围
一、构建
1.1 基本构造函数
public Region() //创建一个空的区域
public Region(Region region) //拷贝一个region的范围
public Region(Rect r) //创建一个矩形的区域
public Region(int left, int top, int right, int bottom) //创建一个矩形的区域
1.2 间接构造
注意:无论调用Set系列函数的Region是不是有区域值,当调用Set系列函数后,原来的区域值就会被替换成Set函数里的区域
// 与基本构造函数 一一对应
//置空:从某种意义上讲置空也是一个构造函数,即将原来的一个区域变量变成了一个空变量,要再利用其它的Set方法重新构造区域。
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)//后面单独讲
由于路径有很多种构造方法,而且可以轻意构造出非矩形的路径,这就摆脱了前面的构造函数只能构造矩形区域的限制。但这里有个问题是要指定另一个区域来取共同的交集,当然如果想显示路径构造的区域,setPath的Region clip参数可以传一个比Path范围大的多的区域,取完交集之后,当然是Path参数所对应的区域喽。机智的孩子
二、绘制区域
对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状
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);
}
}
我们来看个示例:
//初始化Paint
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
//构造一个椭圆路径
Path ovalPath = new Path();
RectF rect = new RectF(50, 50, 200, 500);
ovalPath.addOval(rect, Direction.CCW);
Region rgn = new Region();
rgn.setPath(ovalPath,new Region(50, 50, 200, 1000));
//画出路径
drawRegion(canvas, rgn, paint);
三、区域的合并、交叉等操作
无论是区域还是矩形,都会涉及到与另一个区域的一些操作,比如取交集、取并集等,涉及到的函数有:
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的区域
}
四、主要函数
/**几个判断方法*/
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 class RegionClickView extends CustomView {
Region circleRegion;
Path circlePath;
public RegionClickView(Context context) {
super(context);
mDeafultPaint.setColor(0xFF4E5268);
circlePath = new Path();
circleRegion = new Region();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// ▼在屏幕中间添加一个圆
circlePath.addCircle(w/2, h/2, 300, Path.Direction.CW);
// ▼将剪裁边界设置为视图大小
Region globalRegion = new Region(-w, -h, w, h);
// ▼将 Path 添加到 Region 中
circleRegion.setPath(circlePath, globalRegion);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
int x = (int) event.getX();
int y = (int) event.getY();
// ▼点击区域判断
if (circleRegion.contains(x,y)){
Toast.makeText(this.getContext(),"圆被点击",Toast.LENGTH_SHORT).show();
}
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
// ▼注意此处将全局变量转化为局部变量,方便 GC 回收 canvas
Path circle = circlePath;
// 绘制圆
canvas.drawPath(circle,mDeafultPaint);
}
}