仅供参考
//MARK: -扩展背景色渐变功能
extension UIView {
/// 渐变方向枚举
enum GradientDirection {
case leftToRight // 从左到右
case topToBottom // 从上到下
case leftTopToRightBottom // 左上到右下
case rightTopToLeftBottom // 右上到左下
case custom(start: CGPoint, end: CGPoint) // 自定义方向
/// 计算属性:返回对应方向的起止点
var points: (start: CGPoint, end: CGPoint) {
switch self {
case .leftToRight:
return (CGPoint(x: 0, y: 0.5), CGPoint(x: 1, y: 0.5))
case .topToBottom:
return (CGPoint(x: 0.5, y: 0), CGPoint(x: 0.5, y: 1))
case .leftTopToRightBottom:
return (CGPoint(x: 0, y: 0), CGPoint(x: 1, y: 1))
case .rightTopToLeftBottom:
return (CGPoint(x: 1, y: 0), CGPoint(x: 0, y: 1))
case .custom(let start, let end):
return (start, end)
}
}
}
/// 设置渐变背景色
/// - Parameters:
/// - colors: 渐变颜色数组
/// - direction: 渐变方向,默认从左到右
/// - locations: 颜色位置数组,可选
func addGradientBackground(colors: [UIColor],
direction: GradientDirection = .leftToRight,
locations: [NSNumber]? = nil) {
// 移除已有的渐变层
removeGradientBackground()
// 创建渐变层
let gradientLayer = CAGradientLayer()
gradientLayer.name = "GradientBackground" // 设置标识名称
gradientLayer.frame = bounds
gradientLayer.colors = colors.map { $0.cgColor }
// 设置渐变方向
let (startPoint, endPoint) = direction.points
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
// 设置颜色位置
if let locations = locations {
gradientLayer.locations = locations
}
// 将渐变层插入到最底层
layer.insertSublayer(gradientLayer, at: 0)
}
/// 更新渐变背景层的大小
func updateGradientBackground() {
guard let gradientLayer = layer.sublayers?
.first(where: { $0.name == "GradientBackground" }) as? CAGradientLayer else {
return
}
gradientLayer.frame = bounds
}
/// 移除渐变背景层
func removeGradientBackground() {
layer.sublayers?
.filter { $0.name == "GradientBackground" }
.forEach { $0.removeFromSuperlayer() }
}
}
//MARK: -渐变边框扩展实现
extension UIView {
/// 给 UIView 添加渐变边框
/// - Parameters:
/// - colors: 渐变颜色数组(至少需要2种颜色)
/// - direction: 渐变方向,默认为从左到右
/// - lineWidth: 边框宽度,默认 1
/// - cornerRadius: 圆角半径,默认为视图当前的 `cornerRadius`
func addGradientBorder(colors: [UIColor],
direction: GradientDirection = .leftToRight,
lineWidth: CGFloat = 1,
cornerRadius: CGFloat? = nil) {
guard colors.count > 1 else { return } // 至少需要 2 种颜色
// 移除旧的渐变边框,防止重复添加
removeGradientBorder()
let gradientLayer = CAGradientLayer()
gradientLayer.name = "GradientBorderLayer"
gradientLayer.colors = colors.map { $0.cgColor }
let (startPoint, endPoint) = direction.points
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
gradientLayer.frame = bounds // 设置初始大小
// 创建形状层(用于定义边框路径)
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = lineWidth
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineCap = .round
// 设置圆角(优先使用参数值,否则使用视图当前的圆角)
let effectiveCornerRadius = cornerRadius ?? layer.cornerRadius
shapeLayer.path = UIBezierPath(
roundedRect: bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2),
cornerRadius: effectiveCornerRadius
).cgPath
// 绑定 mask
gradientLayer.mask = shapeLayer
layer.addSublayer(gradientLayer)
}
/// 移除渐变边框
func removeGradientBorder() {
layer.sublayers?.removeAll { $0.name == "GradientBorderLayer" }
}
/// 更新渐变边框(在 `layoutSubviews` 里调用)
func updateGradientBorder() {
guard let gradientLayer = layer.sublayers?.first(where: { $0.name == "GradientBorderLayer" }) as? CAGradientLayer,
let shapeLayer = gradientLayer.mask as? CAShapeLayer else {
return
}
// 更新 `frame`
gradientLayer.frame = bounds
// 重新计算边框路径
let lineWidth = shapeLayer.lineWidth
let cornerRadius = layer.cornerRadius // 使用当前的 `cornerRadius`
shapeLayer.path = UIBezierPath(
roundedRect: bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2),
cornerRadius: cornerRadius
).cgPath
}
}