前言
iOS开发中,经常要跟UI打交道,颜色设置使用频率非常高。在OC中,我们经常使用宏来设置颜色。在Swift中,我们可以利用Swift的语言特性,面向协议,结体体、类、枚举可以遵守协议并实现,同时利用Swift语言协议的默认实现,简化代码,使用属性包装器,限制参数合理的取值范围
常用颜色
- RGB,RGBA
- HEX,HEX+透明度
使用姿势
实现,从一个协议开始
public protocol ColorProvider {
var uiColor: UIColor { get }
var cgColor: CGColor { get }
}
实现结构
其它处理
字符串颜色截取处理
extension String {
func getColor(alpha: CGFloat) -> UIColor {
let set: CharacterSet = CharacterSet.whitespacesAndNewlines
var cstr = trimmingCharacters(in: set).uppercased() as NSString
if cstr.length < 6 { return .clear }
if cstr.hasPrefix("0X") {
cstr = cstr.substring(from: 2) as NSString
} else if cstr.hasPrefix("#") {
cstr = cstr.substring(from: 1) as NSString
}
if cstr.length != 6 { return .clear }
var range = NSRange()
range.location = 0
range.length = 2
// r
let rStr = cstr.substring(with: range);
// g
range.location = 2
let gStr = cstr.substring(with: range)
// b
range.location = 4
let bStr = cstr.substring(with: range)
var r: UInt32 = 0x0, g: UInt32 = 0x0, b: UInt32 = 0x0
Scanner(string: rStr).scanHexInt32(&r)
Scanner(string: gStr).scanHexInt32(&g)
Scanner(string: bStr).scanHexInt32(&b)
return UIColor(
red: CGFloat(r) / 255.0,
green: CGFloat(g) / 255.0,
blue: CGFloat(b) / 255.0,
alpha: alpha
)
}
}
给UIColor扩展一些常用的方法
/// rgb颜色,不用再除255, 使用例子: UIColor(red: 129, green: 21, blue: 12)
///
/// - Parameters:
/// - red: red component.
/// - green: green component.
/// - blue: blue component.
/// - transparency: optional transparency value (default is 1).
convenience public init?(red: Int,
green: Int,
blue: Int,
transparency: CGFloat = 1) {
guard red >= 0 && red <= 255 else { return nil }
guard green >= 0 && green <= 255 else { return nil }
guard blue >= 0 && blue <= 255 else { return nil }
var trans = transparency
if trans < 0 { trans = 0 }
if trans > 1 { trans = 1 }
self.init(
red: CGFloat(red) / 255.0,
green: CGFloat(green) / 255.0,
blue: CGFloat(blue) / 255.0,
alpha: trans
)
}
/// 随机色
public static var random: UIColor {
let range: ClosedRange = 0...255
let red = Int.random(in: range)
let green = Int.random(in: range)
let blue = Int.random(in: range)
return UIColor(red: red, green: green, blue: blue)!
}
属性包装器限制取值范围,提高严谨性
RGB(0~255)取值范围
@propertyWrapper public struct RGBRange<Type: Comparable> {
private var value: Type private var min: Type private var max: Type
public var wrappedValue: Type {
get { value }
set {
value = (min < newValue) ? (max > newValue ? newValue : max) : min
}
}
public init(wrappedValue: Type, min: Type = 0, max: Type = 255) {
#if DEBUG
assert((min <= wrappedValue && max >= wrappedValue), "\nRGB值(wrappedValue)不在范围 [(min), (max)] 区间范围内")
#endif
self.value = wrappedValue
self.min = min
self.max = max
}
}
alpha(0.0~1.0),取值范围
@propertyWrapper public struct AlphaRange {
private var value: CGFloat
private var min: CGFloat
private var max: CGFloat
public var wrappedValue: CGFloat {
get { value }
set {
value = (min < newValue) ? (max > newValue ? newValue : max) : min
}
}
public init(wrappedValue: CGFloat, min: CGFloat = 0.0, max: CGFloat = 1.0) {
#if DEBUG
assert((min <= wrappedValue && max >= wrappedValue), "alpha值 \n(wrappedValue)不在范围 [(min), (max)] 区间范围内")
#endif
self.value = wrappedValue
self.min = min
self.max = max
}
}
使用时,用自定义属性包装器修饰
/// RGB 颜色
public struct RGBAColor {
@RGBRange public var red: Int
@RGBRange public var green: Int
@RGBRange public var blue: Int
@AlphaRange public var alpha: CGFloat
public init(red: Int,
green: Int,
blue: Int,
alpha: CGFloat = 1.0) {
self.alpha = alpha
self.blue = blue
self.green = green
self.red = red
}
}
暗黑模式适配
浅色模式和深色模式下,设置动态
颜色
/// 设置动态颜色,直接设置Int类型的hex值
/// - Parameter light: 浅色模式下的颜色
/// - Parameter dark: 深色模式下的颜色
public static func dynamic(_ light: ColorProvider,
dark: ColorProvider,
alphaComponent alpha: CGFloat? = nil) -> UIColor {
if #available(iOS 13.0, *) {
return UIColor.init { (traitCollection) -> UIColor in let notLight = traitCollection.userInterfaceStyle != .light
if let alpha = alpha {
let darkColor = dark.uiColor.withAlphaComponent(alpha)
let lightColor = light.uiColor.withAlphaComponent(alpha)
return notLight ? darkColor : lightColor
}
let darkColor = dark.uiColor
let lightColor = light.uiColor
return notLight ? darkColor : lightColor
}
} else {
if let alpha = alpha {
return light.uiColor.withAlphaComponent(alpha)
}
return light.uiColor
}
}
总结
通过这种方式,可以统一swift颜色的设置。 优雅,永不过时