渐变进程总是涉及至少两种颜色。颜色与起始点和结束点相关联,范围在0和1之间。除此之外,渐变可以像您想要的那样简单或复杂。图6-1演示了此范围。图6-1中的顶部图像显示了最简单的可能梯度。它从白色(0)变为黑色(1)。底部图像显示了从24个单独色调构建的梯度,参考颜色沉积在等距点处。这个复杂的梯度是从红色到橙色到黄色到绿色等等。
图6-1一个简单的白到黑色渐变和受彩色盘(color wheel)启发的渐变。
如果你以前有使用过渐变,你会知道你可以绘制线性和径向的输出。如果没有,图6-2介绍了这两种样式。在左边,通过从白色(在底部)移动到黑色(在顶部)创建线性渐变。线性渐变沿着您指定的轴绘制颜色。
相反,径向渐变随着它们从开始到结束的演进而改变它们的绘图的宽度。在右边,径向渐变从白色(中心)开始,并在边缘附近延伸到黑色。在该示例中,半径在图像的中间从0开始并且在右边缘的范围结束。随着半径增长,颜色变暗,产生你在这里看到的“球体”外观。
图6-2线性(左)和径向(右)渐变绘制。
您可能无法意识到图6-2中的两个图像都使用相同的源渐变,如图6-1顶部所示。渐变没有形状,位置或任何几何属性。他们只是描述颜色的进度。绘制渐变的方式完全取决于你和你使用的Core Graphics函数调用。
包装CGGradientRef类
CGGradientRef
是Core Foundation类型,它在0.0到1.0的范围内存储任意数量的颜色和起点。您可以通过将两个数组传递给它来构建渐变 - 颜色及其(颜色对应的)位置,如下例所示:
1 | CGGradientRef CGGradientCreateWithColors( |
在进一步查看Core Graphics实现之前,我想休息一下,介绍一个Objective-C的解决方法,当你使用这个类时真的会很有帮助。
总的来说,我发现通过Objective-C包装器使用渐变更容易,而不用担心内存管理和混合使用C和Core Foundation样式的元素,比如这里使用的两个数组。由于没有UIKit提供的渐变包装器和没有等价桥接的方法,我构建了一个Objective-C包装器。这是解决方法发挥作用的地方。
我受到一个小小的属性技巧的帮助,使ARC能够管理Core Foundation引用,就像它是一个正常的Cocoa Touch对象。http://llvm.org 网站描述此功能的方法如下:
GCC introduces __attribute__((NSObject)) on structure pointers to mean “this is an object.” This is useful because many low level data structures are declared as opaque structure pointers, e.g. CFStringRef, CFArrayRef, etc.
你可以使用这个技巧建立一个派生类型。下面是我用于Quartz渐变而定义的类型:
1 | typedef __attribute__((NSObject)) CGGradientRef GradientObject; |
此声明使您能够在使用ARC内存管理的同时,不使用无缝桥接建立基于Core Foundation的类属性类型。这是很重要的,因为,通常情况下,Quartz类不是无缝桥接到UIKit的。您可以使用派生类型来构建使用ARC风格的强引用的属性:
1 |
|
当清单6-1中创建的Gradient
实例被释放时,底层CGGradientRef
也会被释放。您不必构建特殊的dealloc
方法来处理Core Foundation对象。你得到的是一个类,这个类是使用Objective-C接口处理核心图形渐变。您使用UIColor
(类型的)颜色和NSNumber
(类型的)位置的NSArrays
。
注意
正如你在这里看到的,这个属性方法需要显式的类型定义。避免普遍使用其他语言功能,如__typeof。 有关更多详细信息和注意事项,请参阅LLVM文档。使用这种方法我觉得很舒服并且也推荐(使用)这种方法,因为苹果工程师介绍给了我。
清单6-1创建Objective-C渐变类
1 | @interface Gradient () |
本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。