android Graphics(三):区域(Range)

前言:最近几天对画图的研究有些缓慢,项目开始写代码了,只能在晚上空闲的时候捯饬一下自己的东西,今天给大家讲讲区域的相关知识,已经想好后面两篇的内容了,这几天有时间赶紧写出来给大家。有关界面开发的东东内容确实比较多,慢慢来吧,总有一天会不一样。

我自己的一句警言,送给大家:

想要跟别人不一样,你就要跟别人不一样。----- Harvic

相关文章:

1、《android Graphics(一):概述及基本几何图形绘制》
2、《android Graphics(二):路径及文字》
3、《android Graphics(三):区域(Range)》
4、《android Graphics(四):canvas变换与操作》

一、构造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),只知道它可以画出指定的区域就可以了,具体里面是什么意思,后面我们再仔细讲。

[java] view plaincopy

  1. public class MyRegionView extends View {
  2. public MyRegionView(Context context) {
  3. super(context);
  4. // TODO Auto-generated constructor stub
  5. }
  6. @Override
  7. protected void onDraw(Canvas canvas) {
  8. // TODO Auto-generated method stub
  9. super.onDraw(canvas);
  10. //初始化画笔
  11. Paint paint = new Paint();
  12. paint.setColor(Color.RED);
  13. paint.setStyle(Style.FILL);
  14. paint.setStrokeWidth(2);
  15. Region rgn = new Region(10,10,100,100);
  16. //      rgn.set(100, 100, 200, 200);
  17. drawRegion(canvas, rgn, paint);
  18. }
  19. //这个函数不懂没关系,下面会细讲
  20. private void drawRegion(Canvas canvas,Region rgn,Paint paint)
  21. {
  22. RegionIterator iter = new RegionIterator(rgn);
  23. Rect r = new Rect();
  24. while (iter.next(r)) {
  25. canvas.drawRect(r, paint);
  26. }
  27. }
  28. }

看下效果:
                            未开启Set函数时

使用Set函数后,替换为新区域

3、使用SetPath()构造不规则区域

boolean setPath (Path path, Region clip)

参数说明:
Path path:用来构造的区域的路径
Region clip:与前面的path所构成的路径取交集,并将两交集设置为最终的区域

由于路径有很多种构造方法,而且可以轻意构造出非矩形的路径,这就摆脱了前面的构造函数只能构造矩形区域的限制。但这里有个问题是要指定另一个区域来取共同的交集,当然如果想显示路径构造的区域,Region clip参数可以传一个比Path范围大的多的区域,取完交集之后,当然是Path参数所对应的区域喽。机智的孩子。

下面,先构造一个椭圆路径,然后在SetPath时,传进去一个比Path小的矩形区域,让它们两个取交集

[java] view plaincopy

  1. public class MyRegionView extends View {
  2. public MyRegionView(Context context) {
  3. super(context);
  4. // TODO Auto-generated constructor stub
  5. }
  6. @Override
  7. protected void onDraw(Canvas canvas) {
  8. // TODO Auto-generated method stub
  9. super.onDraw(canvas);
  10. //初始化Paint
  11. Paint paint = new Paint();
  12. paint.setColor(Color.RED);
  13. paint.setStyle(Style.FILL);
  14. paint.setStrokeWidth(2);
  15. //构造一个椭圆路径
  16. Path ovalPath = new Path();
  17. RectF rect =  new RectF(50, 50, 200, 500);
  18. ovalPath.addOval(rect, Direction.CCW);
  19. //SetPath时,传入一个比椭圆区域小的矩形区域,让其取交集
  20. Region rgn = new Region();
  21. rgn.setPath(ovalPath,new  Region(50, 50, 200, 200));
  22. //画出路径
  23. drawRegion(canvas, rgn, paint);
  24. }
  25. //这个函数不懂没关系,下面会细讲
  26. private void drawRegion(Canvas canvas,Region rgn,Paint paint)
  27. {
  28. RegionIterator iter = new RegionIterator(rgn);
  29. Rect r = new Rect();
  30. while (iter.next(r)) {
  31. canvas.drawRect(r, paint);
  32. }
  33. }
  34. }

结果如下:

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

对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。RegionIterator类,实现了获取组成区域的矩形集的功能,其实RegionIterator类非常简单,总共就两个函数,一个构造函数和一个获取下一个矩形的函数;
RegionIterator(Region region) //根据区域构建对应的矩形集
boolean next(Rect r) //获取下一个矩形,结果保存在参数Rect r 中

由于在Canvas中没有直接绘制Region的函数,我们想要绘制一个区域,就只能通过利用RegionIterator构造矩形集来逼近的显示区域。用法如下:

[java] view plaincopy

  1. private void drawRegion(Canvas canvas,Region rgn,Paint paint)
  2. {
  3. RegionIterator iter = new RegionIterator(rgn);
  4. Rect r = new Rect();
  5. while (iter.next(r)) {
  6. canvas.drawRect(r, paint);
  7. }
  8. }

上面我们也都看到了它的用法,首先,根据区域构建一个矩形集,然后利用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的参数有下面四个:

[java] view plaincopy

  1. 假设用region1  去组合region2
  2. public enum Op {
  3. DIFFERENCE(0), //最终区域为region1 与 region2不同的区域
  4. INTERSECT(1), // 最终区域为region1 与 region2相交的区域
  5. UNION(2),      //最终区域为region1 与 region2组合一起的区域
  6. XOR(3),        //最终区域为region1 与 region2相交之外的区域
  7. REVERSE_DIFFERENCE(4), //最终区域为region2 与 region1不同的区域
  8. REPLACE(5); //最终区域为为region2的区域
  9. }

至于这六个参数的具体意义,后面给个具体的图给大家显示出来,先举个取交集的例子。

效果图:

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

[java] view plaincopy

  1. //构造两个矩形
  2. Rect rect1 = new Rect(100,100,400,200);
  3. Rect rect2 = new Rect(200,0,300,300);
  4. //构造一个画笔,画出矩形轮廓
  5. Paint paint = new Paint();
  6. paint.setColor(Color.RED);
  7. paint.setStyle(Style.STROKE);
  8. paint.setStrokeWidth(2);
  9. canvas.drawRect(rect1, paint);
  10. canvas.drawRect(rect2, paint);

然后利用上面的两年rect,(rect1和rect2)来构造区域,并在rect1的基础上取与rect2的交集

[java] view plaincopy

  1. //构造两个Region
  2. Region region = new Region(rect1);
  3. Region region2= new Region(rect2);
  4. //取两个区域的交集
  5. region.op(region2, Op.INTERSECT);

最后构造一个填充画笔,将所选区域用绿色填充起来

[java] view plaincopy

  1. Paint paint_fill = new Paint();
  2. paint_fill.setColor(Color.GREEN);
  3. paint_fill.setStyle(Style.FILL);
  4. drawRegion(canvas, region, paint_fill);

全部代码为:

[java] view plaincopy

  1. /**
  2. * created by harvic
  3. * 2014/9/4
  4. */
  5. import android.content.Context;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Paint;
  9. import android.graphics.Rect;
  10. import android.graphics.Region;
  11. import android.graphics.Paint.Style;
  12. import android.graphics.Region.Op;
  13. import android.graphics.RegionIterator;
  14. import android.view.View;
  15. public class MyRegionView extends View {
  16. public MyRegionView(Context context) {
  17. super(context);
  18. // TODO Auto-generated constructor stub
  19. }
  20. @Override
  21. protected void onDraw(Canvas canvas) {
  22. // TODO Auto-generated method stub
  23. super.onDraw(canvas);
  24. //构造两个矩形
  25. Rect rect1 = new Rect(100,100,400,200);
  26. Rect rect2 = new Rect(200,0,300,300);
  27. //构造一个画笔,画出矩形轮廓
  28. Paint paint = new Paint();
  29. paint.setColor(Color.RED);
  30. paint.setStyle(Style.STROKE);
  31. paint.setStrokeWidth(2);
  32. canvas.drawRect(rect1, paint);
  33. canvas.drawRect(rect2, paint);
  34. //构造两个Region
  35. Region region = new Region(rect1);
  36. Region region2= new Region(rect2);
  37. //取两个区域的交集
  38. region.op(region2, Op.INTERSECT);
  39. //再构造一个画笔,填充Region操作结果
  40. Paint paint_fill = new Paint();
  41. paint_fill.setColor(Color.GREEN);
  42. paint_fill.setStyle(Style.FILL);
  43. drawRegion(canvas, region, paint_fill);
  44. }
  45. private void drawRegion(Canvas canvas,Region rgn,Paint paint)
  46. {
  47. RegionIterator iter = new RegionIterator(rgn);
  48. Rect r = new Rect();
  49. while (iter.next(r)) {
  50. canvas.drawRect(r, paint);
  51. }
  52. }
  53. }

其它参数的操作与这个类似,其实只需要改动region.op(region2, Op.INTERSECT);的Op参数值即可,下面就不再一一列举,给出操作后的对比图。

四、其它一些方法

Region类除了上面的一些重要的方法以外,还有一些比较容易理解的方法,我就不再一一列举用法了,下面一并列出给大家

[java] view plaincopy

  1. /**几个判断方法*/
  2. public native boolean isEmpty();//判断该区域是否为空
  3. public native boolean isRect(); //是否是一个矩阵
  4. public native boolean isComplex();//是否是多个矩阵组合
  5. /**一系列的getBound方法,返回一个Region的边界*/
  6. public Rect getBounds()
  7. public boolean getBounds(Rect r)
  8. public Path getBoundaryPath()
  9. public boolean getBoundaryPath(Path path)
  10. /**一系列的判断是否包含某点 和是否相交*/
  11. public native boolean contains(int x, int y);//是否包含某点
  12. public boolean quickContains(Rect r)   //是否包含某矩阵
  13. public native boolean quickContains(int left, int top, int right,
  14. int bottom) //是否没有包含某矩阵
  15. public boolean quickReject(Rect r) //是否没和该矩阵相交
  16. public native boolean quickReject(int left, int top, int right, int bottom); //是否没和该矩阵相交
  17. public native boolean quickReject(Region rgn);  //是否没和该矩阵相交
  18. /**几个平移变换的方法*/
  19. public void translate(int dx, int dy)
  20. public native void translate(int dx, int dy, Region dst);
  21. public void scale(float scale) //hide
  22. 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   谢谢!

时间: 2024-10-16 15:14:49

android Graphics(三):区域(Range)的相关文章

android Graphics(四):canvas变换与操作

前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样.我尽量多画图,让大家更清晰明白. 前几天偶然看到一篇文章,写的朴实无华,充满正能量,我非常喜欢里面的一句话,很像我现在的状态,分享给大家. 人生最纠结的事情不是你甘于平淡,而是你明明不希望平凡却不知道未来应该怎么办. ----摘自<三十岁那年,我的梦想是年薪十万> 相关文章: 1.<android Graphics

android Graphics(二):路径及文字

前言:今天项目进入攻关期,他们改Bug要改疯掉了,主管为了激励大家,给大家发了一封邮件,讲到他对项目和学习的理解,一个很好的图形模型,分享给大家,如图在下面给出:(不便给出原文,我仅做转述)无论是学习还是其它回报,它的回报曲线如下 :蓝色是(成长+付出),红色是回报.有多久可以达到这个红心,要看我们自已的努力,付出了多少专注与汗水.红色线的上挑,是前期厚积薄发的过程,先有异常低调的学习和努力,才会有海阔天空的心态和能量. 相关文章: 1.<android Graphics(一):概述及基本几何图

【转】android Graphics(四):canvas变换与操作

android Graphics(四):canvas变换与操作 分类: 5.andriod开发2014-09-05 15:05 5877人阅读 评论(18) 收藏 举报 目录(?)[+] 前言:前几篇讲解了有关canvas绘图的一些操作,今天更深入一些,讲讲对画布的操作,这篇文章不像前几篇那么容易理解,如果以前没有接触过画布的童鞋可能比较难以理解,为什么会这样.我尽量多画图,让大家更清晰明白. 前几天偶然看到一篇文章,写的朴实无华,充满正能量,我非常喜欢里面的一句话,很像我现在的状态,分享给大家

android Graphics( 五):drawText()详解

前言:但行好事,莫问前程.只需努力每一天. 一.概述 1.四线格与基线 小时候,我们在刚开始学习写字母时,用的本子是四线格的,我们必须把字母按照规则写在四线格内.比如: 那么问题来了,在canvas在利用drawText绘制文字时,也是有规则的,这个规则就是基线!我们先来看一下什么是基线: 可见基线就是四线格中的第三条线!也就是说,只要基线的位置定了,那文字的位置必然是定了的! 2.canvas.drawText() (1).canvas.drawText()与基线 下面我们来重新看看canva

Android中GridView拖拽的效果【android进化三十六】

  最 近看到联想,摩托罗拉等,手机launcher中有个效果,进入mainmenu后,里面的应用程序的图标可以拖来拖去,所以我也参照网上给的代码,写了 一个例子.还是很有趣的,实现的流畅度没有人家的那么好,我只是模仿这种效果,我写的这个拖拽是两个图标之间进行交换,所以,当从一行的某个位置,换到下 一行的另一列的时候,发现有好几个图标都改变位置了,因为是相邻两个交换位置,所以每经过相邻的图标的时候都改变位置.先弄个雏形,以后再更新优化. 转载请标明出处:http://blog.csdn.net/

android.graphics.Matrix

Matrix类包含了一个3x3的矩阵用来改变坐标,它没有一个构造器来初始化它里边的内容,所以创建实例后需要调用reset()方法生成一个标准matrix,或者调用set..一类的函数,比如setTranslate, setRotate,,该函数将会决定matrix如何来改变坐标.SDK里边没有讲述Matrix的3x3矩阵是如何改变点的坐标值的,但是我在代码里边通过打印那9个点的值时,大致可以得到如下结论,9个值[a,b,c,d,e,f,g,h,i],坐标[x,y],当g=0,h=0,i=1,的时

android.graphics.drawable.Drawable注释翻译

/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://w

(转)Android中实现区域平均算法在图片缩放里的应用(缩放图片抗锯齿)

摘要:Android图片缩放效果较差,尤其是将大尺寸的图片缩放成小尺寸的图片时,即便是加了抗锯齿,锯齿现象也比较严重:而java sdk里的区域平均算法缩放图片,效果就比较完美了,因为jdk不能直接用于安卓项目中(类冲突),也没找到可以使用的替代的library,最终只好自己写,在此分享! 正文: 目前我知道的Android API中的传统的图片抗锯齿优化处理无非就是以下相关的设置: //缩放抗锯齿Bitmap.createScaledBitmap(bitmap, width, height,

Android 学习之路--android基础(三)

Android 学习之路--android基础(三) | Talent?C 盒子 盒子 博客 友链 关于 Posts List 作者Talent?C转载请注明出处 前言 上一篇文章我们介绍了 活动(Activity) 的作用及相关用法,我们知道活动是用来给用户展示 UI界面 的,那么在Android中都有哪些UI控件呢?今天就让我们来简单学习几种常见的 UI控件. 如何编写UI界面? Android Studio中为我们提供两种UI界面的编辑方式, 第一种是通过Android Studio 提供