僅供參考
//MARK: -擴(kuò)展背景色漸變功能
extension UIView {
/// 漸變方向枚舉
enum GradientDirection {
case leftToRight // 從左到右
case topToBottom // 從上到下
case leftTopToRightBottom // 左上到右下
case rightTopToLeftBottom // 右上到左下
case custom(start: CGPoint, end: CGPoint) // 自定義方向
/// 計算屬性:返回對應(yīng)方向的起止點
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)
}
}
}
/// 設(shè)置漸變背景色
/// - Parameters:
/// - colors: 漸變顏色數(shù)組
/// - direction: 漸變方向,默認(rèn)從左到右
/// - locations: 顏色位置數(shù)組,可選
func addGradientBackground(colors: [UIColor],
direction: GradientDirection = .leftToRight,
locations: [NSNumber]? = nil) {
// 移除已有的漸變層
removeGradientBackground()
// 創(chuàng)建漸變層
let gradientLayer = CAGradientLayer()
gradientLayer.name = "GradientBackground" // 設(shè)置標(biāo)識名稱
gradientLayer.frame = bounds
gradientLayer.colors = colors.map { $0.cgColor }
// 設(shè)置漸變方向
let (startPoint, endPoint) = direction.points
gradientLayer.startPoint = startPoint
gradientLayer.endPoint = endPoint
// 設(shè)置顏色位置
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: -漸變邊框擴(kuò)展實現(xiàn)
extension UIView {
/// 給 UIView 添加漸變邊框
/// - Parameters:
/// - colors: 漸變顏色數(shù)組(至少需要2種顏色)
/// - direction: 漸變方向,默認(rèn)為從左到右
/// - lineWidth: 邊框?qū)挾?,默認(rèn) 1
/// - cornerRadius: 圓角半徑,默認(rèn)為視圖當(dāng)前的 `cornerRadius`
func addGradientBorder(colors: [UIColor],
direction: GradientDirection = .leftToRight,
lineWidth: CGFloat = 1,
cornerRadius: CGFloat? = nil) {
guard colors.count > 1 else { return } // 至少需要 2 種顏色
// 移除舊的漸變邊框,防止重復(fù)添加
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 // 設(shè)置初始大小
// 創(chuàng)建形狀層(用于定義邊框路徑)
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = lineWidth
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.black.cgColor
shapeLayer.lineCap = .round
// 設(shè)置圓角(優(yōu)先使用參數(shù)值,否則使用視圖當(dāng)前的圓角)
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` 里調(diào)用)
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 // 使用當(dāng)前的 `cornerRadius`
shapeLayer.path = UIBezierPath(
roundedRect: bounds.insetBy(dx: lineWidth / 2, dy: lineWidth / 2),
cornerRadius: cornerRadius
).cgPath
}
}