3

I have a UIProgressView and want to have a corner radius for the filled part (progress part) , I am able to make the corners of the progress view rounded using the cornerRadius property , I also want to the filled progress edge to be rounded.Please find below how the progress bar looks now.

enter image description here

I want the edge of the red portion to be rounded.

I tried to set the progressImage with an image having rounded edges , while it solves the issue , the image itself is far stretched , the radii in the corners are not maintained.

The other thing I tried was to draw a rectangle and fill it with the progress color and convert it to a UIImage with the following code and set it as progress Image , in this case , the image is always black , not sure what I am missing. Please find below the code for converting uiview to uiimage

class func imageWithView(view: UIView) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
    view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
    let img = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return img!
}
  • Possible duplicate of [How to make rounded corner progress bar in swift?](https://stackoverflow.com/questions/32114779/how-to-make-rounded-corner-progress-bar-in-swift) – Paul Roub Nov 16 '17 at 22:47
  • https://stackoverflow.com/questions/40925453/making-uiprogressview-rounded-corners – BollMose Oct 23 '19 at 08:14

2 Answers2

7

I used this code to filled progress edge to be rounded.

myProgressView.layer.sublayers![1].cornerRadius = 12
myProgressView.subviews[1].clipsToBounds = true
Ilyar
  • 71
  • 1
  • 3
2

This question is some months old, but since I had the same doubt, I want to share the answer that I found. I couldn't find a way to do this by just modifying UIProgressView, directly. Seems like the easiest way is to customise a view to look like a progress bar. I based my answer on Umair Afzal's in this question: https://stackoverflow.com/a/41373525/1775356 It's a bit modified for my needs and it is also updated for Swift 3.

import Foundation

import UIKit

class CustomHorizontalProgressView: UIView {
    var color: UIColor = UIColor.red
    var progress: CGFloat = 0.0 {

        didSet {
            setNeedsDisplay()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        setup()
    }

    func setup() {
        self.backgroundColor = color.withAlphaComponent(0.4)
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)

        var progress = self.progress
        progress = progress > 1.0 ? progress / 100 : progress

        self.layer.cornerRadius = self.frame.height / 2.0

        let margin: CGFloat = 0
        var width = (self.frame.width - margin)  * progress
        let height = self.frame.height - margin

        if (width < height) {
            width = height
        }

        let pathRef = UIBezierPath(roundedRect: CGRect(x: margin / 2.0, y: margin / 2.0, width: width, height: height), cornerRadius: height / 2.0)

        color.setFill()
        pathRef.fill()

        UIColor.clear.setStroke()
        pathRef.stroke()

        pathRef.close()            
    }
}

I'm using a color for the progress tint and the same color with alpha 40% for the background tint. This is easily changeable by selecting another background color. For the record, the outside rounded corners were added in the IB. This can also be done programmatically. It looks like this:

Valeriy Van
  • 1,851
  • 16
  • 19
Iris
  • 291
  • 5
  • 10
  • It's wrong to call setNeedsDisplay in drawRect (now it's done indirectly). What's needed - call setNeedsDisplay which triggers drawRect. – Valeriy Van Oct 19 '17 at 15:43
  • Thanks for the heads up! I decided to approve your edit because if I had rejected it as reviewed by two other users, I would have just edited it as you suggested. – Iris Oct 19 '17 at 18:53
  • setting the background color doesn't work. It fills the entire view not just the rounded portion. – Alan Nov 22 '17 at 20:07