使用Quartz绘制带阴影的圆角图

最近在做iOS开发的时候,遇到这样的需求:需要开发一个高度自适应的控件,背景使用图案平铺,控件下方两个角为圆角,控件的下边有5像素宽的阴影。具体如图所示:

需求效果图

方案A

在做这个需求时首先想到是用colorWithPatternImage来平铺图片,然后使用CALayer添加阴影。

不过这样做的严重缺陷是阴影被裁切掉了。

方案B

所以考虑使用Quartz的CGContextDrawTiledImage来平铺背景,使用layer制造阴影。

这样做虽然可以大概的实现需求,不过阴影的宽度不可控制。

方案C

于是我尝试使用Quartz的CGContextSetShadowWithColor来绘制阴影,但是怎么绘制阴影呢?使用CGContextDrawTiledImage平铺背景时会占满指定的区域,这样也有没有了绘制阴影的空间。

在stackoverflow搜索了一圈,有人建议先使用固定色填充圆角区域,再在这个区域平铺图片。

这个方案比上个方案好了很多,不过细心的人可能会发现圆角的阴影有深色的锯齿,不够协调。原因是阴影是根据固定色生成的,在处理边界过度时是从固定色过度来的。

方案D

那有没有办法让阴影根据图片来生成呢?我想到了CGContextDrawImage方法。先在一个特殊的context生成平铺图,然后在当前的context使用CGContextDrawImage来绘制图片,这样绘制图片的同时会产生相应的阴影。

结语

作为初学者,对Quartz也只是一知半解。尝试过程中发现绘制的时候一定要注意顺序,否则会出现各种奇怪的问题。Quartz是个强大东西,要好好利用还需跟多的尝试。

另附上本文的源代码:https://github.com/ohsc/CodeBox-of-Cocoa/tree/master/RoundedCornerImageWithShadow

四个方案运行效果图:

运行结果图