Android 笔记 - 从图像中扣一个洞出来 ……

本文探讨了在Android中从图像中创建一个圆形洞口的两种方法,包括使用paint的strokeWidth和clipPath进行动画效果。虽然clipPath在静态抠图时表现良好,但在动画中仍存在帧数问题。最终,作者找到了使用canvas的clip系列方法创建连贯揭示动画的合理解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如题

我发现,用canvas绘图如果只是创造一些图形倒还容易,无非就是麻烦一点。
但是我居然一下想不到怎么从图像中扣出一个透明的圆形来。

方形的很容易嘛,可以在四周绘制几个方形,把中间空出来就可以了,已经实现了。但是没办法让中间空出一个圆形的来。

比如说,类似扫码的界面,就中间一个扫码区域可用,其他区域是半透明的,或者是一个蒙版,把需要特写的地方空出来,其他地方是半透明的。

找到了两个解决办法

第一个方法:使用paint,setStrokeWidth.
在绘图的时候,需要设置paint,如果绘制一个圆形,把paint设置成stroke,就会绘制一个带边线的圆形,但是效果不是上面提到的那样的中空的。

但是,如果把strokeWidth设置的很宽,就可以模拟出这种效果。具体的试一下就知道了。

其中,设置的宽度是在原边线的位置,往外和往内各绘制0.5个宽度,加起来就是1个宽度了。

缺点:空出来的空间大了还好,看不出来毛病(几乎看不出来)。如果中间的圆小了,就看得出来那实际上是个多边形,貌似是个6变形。

第二个方法,绘图的时候,paint有个方法 :setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
如果设置了这个,那么,绘出来的图形会在之前绘制的图形上面扣出来,比如,之前绘制的是个方形,然后在中间绘制一个圆形,那么这个圆形就会在中间扣出来,而不是原来的叠加圆形。这个貌似是最容易想到的过程。但是
缺点:貌似不能应用在硬件加速的组件上。如果直接在onDraw里面绘制,那需要关闭硬件加速,不用全局关,只要设置当前view关闭硬件加速即可。如果是绘制在bitmap上,然后在onDraw里面绘制bitmap,倒是可以不关闭硬件加速。

但是,我现在需要做一个揭露效果,就是开始描述的那个圆形慢慢扩大,揭露出底下的内容。实际上,这个效果在5.0以后,material design里面直接提供了一个方法ViewAnimationUtils.createCircularReveal(),直接就可以用。我现在是想用一个自己的思路实现这个效果。(好吧,就算是重复发明轮子吧)
如果使用第二个方法,那么揭露动画效果非常不连贯,就像帧数很低一样。即便是不关闭硬件加速的那种方法也是如此。

总结

如果使用普通的遮罩,并且在中间扣出一个洞来显示内容,第二个办法更好,可以扣的比较圆。
但是如果做动画,效果不行,用第一个办法,勉强可以。

因此,还需要继续探索有没有其他解决途径。

参考
参考

貌似最合理的解决办法来了

好,才过一会儿,我就在网上找到了最合理的解决办法。

canvas有一系列的clip方法,包括两个clipRect和两个clipPath
对应另种切割,分别是方形切割和path切割。如果要切割圆形,就用第二个也就是clipPath

两组方法里面参数类似,就拿clipPath来讲,分别是
clipPath(Path path)clipPath(Path path, Region.Op op)
如果要切割区域,需要调用两次,第一次调用第一个方法,第二次第二个,
其中第二个方法的op参数确定了切割类型

   //DIFFERENCE是第一次不同于第二次的部分显示出来
   //REPLACE是显示第二次的
   //REVERSE_DIFFERENCE 是第二次不同于第一次的部分显示
   //INTERSECT交集显示
   //UNION全部显示
   //XOR补集 就是全集的减去交集剩余部分显示


DIFFERENCE是第一次不同于第二次的部分显示出来A-B-------

REPLACE是显示第二次的B******

REVERSE_DIFFERENCE 是第二次不同于第一次的部分显示--------

INTERSECT交集显示A-(A-B)*******

UNION全部显示A+B******

XOR补集 就是全集的减去交集剩余部分显示--------

流程是,先调用clip方法两次,确定切割区域

然后再调用普通的绘图方法,绘制图形

最后显示出来的就是clip方法确定的东西了。

用这个方法来绘制静态的抠图没问题,经过测试发现,做一个揭露动画的话,效果也比之前介绍的那个需要关闭硬件加速的好多了,帧数正常,我肉眼观察来看,跟官方提供的那个ViewAnimationUtils.createCircularReveal()没区别。

http://www.cnblogs.com/bbglz/p/4794519.html
http://1025250620.iteye.com/blog/1933226

所以,重复发明轮子成功…………

好吧,这种事情还是研究下就算了,要用的话还是用官方提供的那个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值