具有颜色渐变到标签特定高度的 UILabel
UILabel with color gradient to certain height of the label
我想实现下图中的效果 - UILabel
显示进度 X 作为从底部到 X%[ 的渐变=28=] 标签的高度。标签的剩余 (100 - X)% 将具有不同的颜色。
我现在唯一想到的是创建两个 UIViews
一个灰色背景和一个渐变颜色。将渐变视图放在灰色视图上方,并设置它的高度以匹配当前进度。然后简单地使用标签作为这两个视图的掩码。为了更好地说明,我附上了一张描述我建议的解决方案的图片。虽然我对它不满意,因为它不是很优雅。
是否有可能以一种不同的、更优雅的方式实现这一点?理想情况下只是通过子类化 UILabel
.
您可以继承 UILabel
并在 draw(_ rect: CGRect)
函数中绘制您想要的内容。或者如果你想快速完成它,你也可以子类化并添加渐变子视图。不要忘记在 layoutSubviews()
函数中调整它的大小。
您可以将核心动画与 CATextLayer 和 CAGradientLayer 一起使用。
import PlaygroundSupport
let bgView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
bgView.backgroundColor = UIColor.black
PlaygroundPage.current.liveView = bgView
let textLayer = CATextLayer()
textLayer.frame = bgView.frame
textLayer.string = "70"
textLayer.fontSize = 60
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bgView.frame
gradientLayer.colors = [
UIColor.gray.cgColor,
UIColor(red: 1, green: 122.0/255.0, blue: 0, alpha: 1).cgColor,
UIColor(red: 249.0/255.0, green: 1, blue: 0, alpha: 1).cgColor
]
//Here you can adjust the filling
gradientLayer.locations = [0.5, 0.51, 1]
gradientLayer.mask = textLayer
bgView.layer.addSublayer(gradientLayer)
您可以使用图层和蒙版来执行此操作,但实际上仅使用图案图像中的 UIColor 设置文本颜色会更容易。这段代码可以工作,尽管 subclass UILabel 并为 class 提供应用和/或更新图像的方法可能更好。我说这更容易,因为我发现处理文本层有点痛苦以获得完美的大小,因为标签可以使用 adjustsFontSizeToFitWidth 来改变它们的字体大小。
override func viewDidLayoutSubviews() {
label.textColor = UIColor(patternImage: partialGradient(forViewSize: label.frame.size, proportion: 0.65))
}
func partialGradient(forViewSize size: CGSize, proportion p: CGFloat) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.darkGray.cgColor)
context?.fill(CGRect(origin: .zero, size: size))
let c1 = UIColor.orange.cgColor
let c2 = UIColor.red.cgColor
let top = CGPoint(x: 0, y: size.height * (1.0 - p))
let bottom = CGPoint(x: 0, y: size.height)
let colorspace = CGColorSpaceCreateDeviceRGB()
if let gradient = CGGradient(colorsSpace: colorspace, colors: [c1, c2] as CFArray, locations: [0.0, 1.0]){
// change 0.0 above to 1-p if you want the top of the gradient orange
context?.drawLinearGradient(gradient, start: top, end: bottom, options: CGGradientDrawingOptions.drawsAfterEndLocation)
}
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
我想实现下图中的效果 - UILabel
显示进度 X 作为从底部到 X%[ 的渐变=28=] 标签的高度。标签的剩余 (100 - X)% 将具有不同的颜色。
我现在唯一想到的是创建两个 UIViews
一个灰色背景和一个渐变颜色。将渐变视图放在灰色视图上方,并设置它的高度以匹配当前进度。然后简单地使用标签作为这两个视图的掩码。为了更好地说明,我附上了一张描述我建议的解决方案的图片。虽然我对它不满意,因为它不是很优雅。
是否有可能以一种不同的、更优雅的方式实现这一点?理想情况下只是通过子类化 UILabel
.
您可以继承 UILabel
并在 draw(_ rect: CGRect)
函数中绘制您想要的内容。或者如果你想快速完成它,你也可以子类化并添加渐变子视图。不要忘记在 layoutSubviews()
函数中调整它的大小。
您可以将核心动画与 CATextLayer 和 CAGradientLayer 一起使用。
import PlaygroundSupport
let bgView = UIView(frame: CGRect(x: 0, y: 0, width: 80, height: 80))
bgView.backgroundColor = UIColor.black
PlaygroundPage.current.liveView = bgView
let textLayer = CATextLayer()
textLayer.frame = bgView.frame
textLayer.string = "70"
textLayer.fontSize = 60
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bgView.frame
gradientLayer.colors = [
UIColor.gray.cgColor,
UIColor(red: 1, green: 122.0/255.0, blue: 0, alpha: 1).cgColor,
UIColor(red: 249.0/255.0, green: 1, blue: 0, alpha: 1).cgColor
]
//Here you can adjust the filling
gradientLayer.locations = [0.5, 0.51, 1]
gradientLayer.mask = textLayer
bgView.layer.addSublayer(gradientLayer)
您可以使用图层和蒙版来执行此操作,但实际上仅使用图案图像中的 UIColor 设置文本颜色会更容易。这段代码可以工作,尽管 subclass UILabel 并为 class 提供应用和/或更新图像的方法可能更好。我说这更容易,因为我发现处理文本层有点痛苦以获得完美的大小,因为标签可以使用 adjustsFontSizeToFitWidth 来改变它们的字体大小。
override func viewDidLayoutSubviews() {
label.textColor = UIColor(patternImage: partialGradient(forViewSize: label.frame.size, proportion: 0.65))
}
func partialGradient(forViewSize size: CGSize, proportion p: CGFloat) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.darkGray.cgColor)
context?.fill(CGRect(origin: .zero, size: size))
let c1 = UIColor.orange.cgColor
let c2 = UIColor.red.cgColor
let top = CGPoint(x: 0, y: size.height * (1.0 - p))
let bottom = CGPoint(x: 0, y: size.height)
let colorspace = CGColorSpaceCreateDeviceRGB()
if let gradient = CGGradient(colorsSpace: colorspace, colors: [c1, c2] as CFArray, locations: [0.0, 1.0]){
// change 0.0 above to 1-p if you want the top of the gradient orange
context?.drawLinearGradient(gradient, start: top, end: bottom, options: CGGradientDrawingOptions.drawsAfterEndLocation)
}
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}