1.1的详细解释。区域操作组合模式
其实难度无非就是这个。Region代表区域,意思是画布层上的封闭区域!当然,有时间可以慢慢推导这个类,我们一般只关注它的一个枚举值:OP。
我们来看看每个枚举值的作用:假设两个裁剪区域A和B,那么我们调用Region对应的枚举值。Op:
差异:A和B的差异范围,即A-B,只显示该范围内的绘图内容;
相交:即A和b的相交范围,只显示该范围内的绘图内容。
并集:即A和B的并集范围,即显示两者包含的范围的绘图内容;
XOR:A和B的互补范围,本例中为A除B以外的范围,只显示该范围内的绘图内容;
reverse _ difference:B和A的差值范围,即B-A,只显示该范围内的绘图内容;
替换:无论A和B的收集状态如何,都会显示B的范围。若与A相交,则覆盖A的相交范围;
如果你学过汇编,那么画一个维恩(韦恩图)就清楚了。你还没学会吗?没事,我们写个例子试试相应的结果吧~!写一个初始化笔刷和画一个矩形的方法3360
private void init(){ MP aint=new Paint();MP aint . setantialias(true);mpaint . setstrokewidth(6);MP int . set color(get resources()。getColor(R.color .腮红));} private void draw scene(Canvas Canvas){ Canvas . draw rect(0,0,200,200,mPaint);}操作差异:
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (50,50,150,150,region . op . difference);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始,切割出两个100*100的矩形,切割结果如下:
A和B的差集=A-(A和B相交的部分)
操作相交:
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (50,50,150,150,region . op . intersect);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始,裁剪出两个100*100的矩形,裁剪结果为:A和B的交集=A和B的交集。
操作联盟:
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (40,40,140,140,region . op . union);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始裁剪两个100*100的矩形,裁剪结果为:A和B的并集=A的面积B。
异或运算:
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (50,50,150,150,region . op . xor);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始裁剪两个100*100的矩形,裁剪结果为:A和B的补数=A和B的集合-A和B的交集。
Op . REVERSE _差异:
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (50,50,150,150,region . op . reverse _ difference);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始,裁剪出两个100*100的矩形,裁剪结果为:B和A的差集=B-A和B的交集。
操作替换
canvas.clipRect(10,10,110,110);//第一个canvas.clirect (50,50,150,150,region . op . replace);//第二个drawScene(画布);结果:
从(10,10)和(50,50)开始裁剪两个100*100的矩形,裁剪结果如下:无论A和B的聚合状态如何,B的范围都会完整显示,如果与A相交,则覆盖A的相交范围;
2.使用2的示例。区域。Op:
例子来自:安卓2D图形学习(二),画布第二章,画布裁剪和区域,区域迭代器。
操作效果图:
关键代码MyView.java:
/** *由Jay于2015/11/10 0010创作。*/公共类MyView扩展视图{ private Bitmap mBitmap=nullprivate int limit length=0;//private int宽度;私有int heigthprivate static final int CLIP _ HEIGHT=50;私有布尔状态=隐藏;//显示或隐藏的状态,以hide private static final boolean show=true开头;//显示图片private static final布尔hide=false//隐藏图片public my view(context context){ this(context,null);} public MyView(Context context,AttributeSet attrs){ super(Context,attrs);mbit map=bitmapfactory . decode resource(get resources(),r . MIP map . img _ meizi);limit length=width=mbit map . getwidth();heigth=mbit map . get height();} public MyView(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr);} @ Override protected void onDraw(Canvas Canvas){ Region Region=new Region();int I=0;while(I * clip _ height=height){//计算clip (I% 2==0)的区域if { region . union(new rect(0,I * clip _ height,极限长度,(I 1)* clip _ height));} else { region . union(new Rect(width-limit length,i * CLIP_HEIGHT,width,(I 1)* CLIP _ HEIGHT));}我;} canvas.clipRegion(区域);canvas.drawBitmap(mBitmap,0,0,new Paint());If (status==HIDE) {//如果此时隐藏限制长度-=10;if(limit length=0)status=SHOW;} else {//如果此时显示limit length=5;if(limit length=width)status=HIDE;} invalidate();}}实施分析:
初始化时,获取宽度和高度,然后循环。把画面分成线条是可以理解的。循环条件是:i *每条线的高度不大于高度,然后线分两种情况。区域的并集叫做,其实就是UNINO的切割方式。最后对此时图片是否显示做出判断,对隐藏和显示的情况区别处理,最后调用invalid()进行重绘!很简单。自己看懂吧~
还有一点:Canvas的变换对clipRegion没有影响。
3.3.clipRect方法的详细说明:
ClipRect提供了七个重载方法:
参数介绍如下:
Rect:Rect对象,用于定义裁剪区域的范围。Rect和RectF功能相似,但精度与提供的方法不同。
Left:矩形裁剪区域的左侧位置。
顶部:矩形裁剪区域的顶部位置。
右侧:矩形裁剪区域的右侧位置。
底部:矩形裁剪区域的底部位置。
Op:作物区域的组合
以上四个值可以是浮点数,也可以是整数。
使用示例:
MP aint=new Paint();MP aint . setantialias(true);mPaint.setColor(Color。黑色);mpaint . settextsize(60);canvas.translate(300,300);canvas.clipRect(100,100,300,300);//设置显示范围canvas.drawColor(Color。白色);//canvas.drawText(\白底(\ ‘双11,继续吃我的狗粮.\ ‘,150,300,mPaint);//绘制字符串运行结果:
从上面的例子,不知道你有没有发现?ClipRect会受到画布变换的影响,白色的区域就是没有花的区域,所以clipRect把画布切开,我们的画图就是在这个切开的画布上完成的!此区域外禁止显示!
4.4.clipPath方法的详细说明:
与clipRect相比,clipPath只有两个重载方法,使用起来非常简单。自己画一个Paht然后传进去!
使用示例:
下面是我们之前在ImageView中写的循环ImageView的例子的复用~
实施代码:
自定义图像视图:RoundImageView.java
/** *由编码猪于2015/7/18 0018创建100 */公共类圆形图像视图扩展ImageView { private Bitmap mbit map;private Rect mRect=new Rect();private PaintFlagsDrawFilter pdf=new PaintFlagsDrawFilter(0,Paint .ANTI _ ALIAS _ FLAG);私漆MP aint=new Paint();私有路径mPath=新路径();public round imageview(Context Context,AttributeSet attrs){ super(Context,attrs);init();} //传入一个位图对象public void set Bitmap(Bitmap Bitmap){ this。mbit map=位图;} private void init(){ MP aint。设置样式(绘画.风格。笔画);mPaint.setFlags(Paint .ANTI _ ALIAS _ FLAG);MP不是。setantialias(真);//抗锯尺} @ Override protected void onDraw(Canvas Canvas){ super。onDraw(帆布);if(mbit map==null){ return;} mRect.set(0,0,getWidth(),getHeight());canvas.save()。画布。setdrawfilter(pdf);mPath.addCircle(getWidth()/2,getWidth()/2,getHeight()/2,Path .方向。CCW);canvas.clipPath(mPath,Region .Op。替换);canvas.drawBitmap(mBitmap,null,mRect,MP aint);canvas.restore().}}布局代码:activity_main.xml:
MainActivity.java:
公共类主要活动扩展app compat活动{私轮imageview img _ round@ Override protected void onCreate(Bundle savedInstanceState){ super。onCreate(savedInstanceState);setContentView(r . layout。活动_主);img _ round=(round imageview)findViewById(r . id。img _ round);位图位图=位图工厂。解码资源(get resources(),r . MIP map。meinv);img_round.setBitmap(位图);}}运行效果图:
另外使用该方法制作的圆角图片会有锯齿明显,即使你为油漆、帆布设置了抗锯齿也没用~假如你要求高的,可以使用Xfermode-PorterDuff设置图像混排来实现,基本没锯齿,可见:安卓基础入门教程——8.3.6油漆应用程序接口之—— Xfermode与波特达夫详解(三)
5.本节示例代码下载:
CanvasDemo2.zip
XfermodeDemo1.zip
本节小结:
好的,本节给大家讲解了下帆布中剪切有个的三个方法:clipPath(),clipRect(),clipRegion(),难点应该是在最后一个上,六种不同的外科手术组合方式,其实也不难,集合的概念而已,放在开头,消化了就好,而clipPath(),clipRect()则没什么难点~对喔,
暂无讨论,说说你的看法吧