带有渐变的iOS UIProgressView

时间:2016-12-31 12:19:04

标签: ios gradient progress uiprogressview cagradientlayer

是否可以使用从左到右的渐变创建自定义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

但不幸的是,渐变不明显。还有其他想法吗?

3 个答案:

答案 0 :(得分:6)

我遇到了同样的问题并通过创建渐变自定义视图解决了这个问题,然后我将其转换为图像并将其指定为进度视图轨迹图像。

然后我水平翻转进度,使进度条成为背景,轨迹图像成为前景。

这具有显示下方渐变图像的视觉效果。

您只需记住将百分比反转为非常简单,请参阅下面的示例按钮和代码:

enter image description here enter image description here

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)
        }
    }

}

答案 1 :(得分:6)

看看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的{​​{1}},如下所示:

progressImage

答案 2 :(得分:1)

乔治想出了一种非常聪明的方法。如果您想要更简单的解决方案,请打开UIProgressView文档,这里有一个名为 progressImage 的属性。

所以,我只是这样使它工作:

progressView.progressImage = UIImage(named: "your_gradient_progress_icon")
progressView.trackTintColor = UIColor.clear

之后:

progressView.setProgress(currentProgress, animated: true)