带有渐变的 iOS UIProgressView
Posted
技术标签:
【中文标题】带有渐变的 iOS UIProgressView【英文标题】:iOS UIProgressView with gradient 【发布时间】:2016-12-31 12:19:03 【问题描述】:是否可以创建一个从左到右渐变的自定义 ui 进度视图?
我已经用下面的代码试过了:
let gradientLayer = CAGradientLayer()
gradientLayer.frame = self.frame
gradientLayer.anchorPoint = CGPoint(x: 0, y: 0)
gradientLayer.position = CGPoint(x: 0, y: 0)
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0);
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.0);
gradientLayer.colors = [
UIColor.red,
UIColor.green
]
// Convert to UIImage
self.layer.insertSublayer(gradientLayer, at: 0)
self.progressTintColor = UIColor.clear
self.trackTintColor = UIColor.black
但不幸的是渐变是不可见的。还有其他想法吗?
【问题讨论】:
cocoacontrols.com/controls/amgprogressview 您是否将其作为子视图添加到您的视图中? 我在storyboard里面添加了,在init函数中调用了上面的代码。 【参考方案1】:看UIProgressView
documentation,有这个属性:
progressImage
如果您提供自定义图像,progressTintColor 属性将被忽略。
考虑到这一点,最懒惰的方法是创建渐变图像并将其设置为progressImage
我调整了 this extension 使其更清洁、可扩展和更安全。
fileprivate extension UIImage
static func gradientImage(with bounds: CGRect,
colors: [CGColor],
locations: [NSNumber]?) -> UIImage?
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = colors
// This makes it horizontal
gradientLayer.startPoint = CGPoint(x: 0.0,
y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0,
y: 0.5)
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
guard let image = UIGraphicsGetImageFromCurrentImageContext() else return nil
UIGraphicsEndImageContext()
return image`
现在我们已经有了“动态”创建渐变图像的方法,下面是如何使用它:
let gradientImage = UIImage.gradientImage(with: progressView.frame,
colors: [UIColor.red.cgColor, UIColor.green.cgColor],
locations: nil)
从那里,您只需设置您的progressView
的progressImage
,如下所示:
// I'm lazy...don't force unwrap this
progressView.progressImage = gradientImage!
progressView.setProgress(0.75, animated: true)
【讨论】:
你需要确保progressView.frame有一个宽度和高度,否则它会在gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
上崩溃【参考方案2】:
我遇到了同样的问题,并通过创建渐变自定义视图来解决它,然后我将其转换为图像并将其分配为进度视图轨道图像。
然后我水平翻转进度,使进度条成为背景,轨迹图像成为前景。
这具有露出下方渐变图像的视觉效果。
您只需要记住反转您的百分比,这非常简单,请参见下面的示例按钮和代码:
SWIFT 3 示例:
class ViewController: UIViewController
@IBOutlet weak var progressView: UIProgressView!
@IBAction func lessButton(_ sender: UIButton)
let percentage = 20
let invertedValue = Float(100 - percentage) / 100
progressView.setProgress(invertedValue, animated: true)
@IBAction func moreButton(_ sender: UIButton)
let percentage = 80
let invertedValue = Float(100 - percentage) / 100
progressView.setProgress(invertedValue, animated: true)
override func viewDidLoad()
super.viewDidLoad()
//create gradient view the size of the progress view
let gradientView = GradientView(frame: progressView.bounds)
//convert gradient view to image , flip horizontally and assign as the track image
progressView.trackImage = UIImage(view: gradientView).withHorizontallyFlippedOrientation()
//invert the progress view
progressView.transform = CGAffineTransform(scaleX: -1.0, y: -1.0)
progressView.progressTintColor = UIColor.black
progressView.progress = 1
extension UIImage
convenience init(view: UIView)
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.init(cgImage: (image?.cgImage)!)
@IBDesignable
class GradientView: UIView
private var gradientLayer = CAGradientLayer()
private var vertical: Bool = false
override func draw(_ rect: CGRect)
super.draw(rect)
// Drawing code
//fill view with gradient layer
gradientLayer.frame = self.bounds
//style and insert layer if not already inserted
if gradientLayer.superlayer == nil
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = vertical ? CGPoint(x: 0, y: 1) : CGPoint(x: 1, y: 0)
gradientLayer.colors = [UIColor.green.cgColor, UIColor.red.cgColor]
gradientLayer.locations = [0.0, 1.0]
self.layer.insertSublayer(gradientLayer, at: 0)
【讨论】:
【参考方案3】:乔治想出了一个非常聪明的方法。如果你想要一个更简单的解决方案,打开 UIProgressView 文档,有一个名为 progressImage 的属性。
所以,我只是让它像这样工作:
progressView.progressImage = UIImage(named: "your_gradient_progress_icon")
progressView.trackTintColor = UIColor.clear
之后:
progressView.setProgress(currentProgress, animated: true)
【讨论】:
以上是关于带有渐变的 iOS UIProgressView的主要内容,如果未能解决你的问题,请参考以下文章