这是我参与更文挑战的第16天,活动详情查看: 更文挑战
本文为在阅读 Kingfisher 源码时的收货。
Kingfisher 中有一个协议 ImageModifier
,用于在图片缓存序列化之后、实际使用之前修改图像的属性。此修改后的图片仅用于渲染目的,而不会影响到序列化、缓存的过程。
作者提供了三个实现 ImageModifier
协议的结构体 RenderingModeImageModifier
,FlipsForRightToLeftLayoutDirectionImageModifier
,AlignmentRectInsetsImageModifier
。下面分别介绍一下各自的使用场景。
RenderingModeImageModifier
用于修改 UIImage 的 renderingMode
属性,定义如下:
public enum RenderingMode : Int {
case automatic = 0 // Use the default rendering mode for the context where the image is used
case alwaysOriginal = 1 // Always draw the original image, without treating it as a template
case alwaysTemplate = 2 // Always draw the image as a template image, ignoring its color information
}
复制代码
- automatic:根据当前所处的上下文来决定是渲染图片的原始状态,或是当做模板来渲染。例如 UINavigationBar、UITabBar、UIToolBar、UISegmentedControl 等控件,会自动把其上面的图片(foreground images)当做模板来渲染;而 UIImageView、UIWebView 则会渲染图片的原始状态。
- alwaysOriginal:使用原始状态渲染。
- alwaysTemplate:当做模板来渲染。
模板(template)就是忽略掉了图片的所有不透明的颜色信息,取而代之的是它所在的控件的 tintColor。创建 UIImage 时, 默认的 renderingMode
为 .automatic
。所以在设置 UINavigationBar 的图片时,图片会显示为 tintColor
的纯色图片。
所以,在 UINavigationBar、UITabBar 这些具有上下文的控件上加载网络图片时,可以使用 RenderingModeImageModifier
来修改图片。
FlipsForRightToLeftLayoutDirectionImageModifier
用于在使用 UIImage 之前调用 imageFlippedForRightToLeftLayoutDirection()
。当 UIImage 处于从右到左的布局(right-to-left layout)时,会返回一个将当前图片水平翻转后的新 UIImage。
在处理国际化,特别是要考虑从右到左阅读的国家时,可以使用 FlipsForRightToLeftLayoutDirectionImageModifier
来处理图片。
AlignmentRectInsetsImageModifier
用于在使用 UIImage 之前调用 withAlignmentRectInsets(_:)
。
如果 UIImageView 要显示的图片包含阴影、徽章等装饰元素,在给 UIImageView 添加约束时,有两种处理方式:
- 设置 UIImageView 为整个图片的大小;
- 忽略装饰元素,根据核心区域约束 UIImageView 的大小。此时可以通过修改 UIImage 的 alignmentRect,调整对齐矩形,插入内边距来达到目的。
如果是UIView,则可以通过重写UIView的方法alignmentRectInsets,调整对齐矩形。
alignmentRect 可视化
在 Scheme 中的 Arguments 中添加 -UIViewShowAlignmentRects YES
可以可视化 alignmentRect。
let image = UIImage(named: "HOT")
leftImageView.image = image?.withAlignmentRectInsets(UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 10))
rightImageView.image = image
复制代码
HOT 图片为:
运行时的效果