Making UIProgressView Rounded corners

前端 未结 13 1686
旧巷少年郎
旧巷少年郎 2021-02-07 13:59

I have created a UIProgressView with following properties

progressView.progressTintColor = UIColor.appChallengeColorWithAlpha(1.0)
progressView.trac         


        
相关标签:
13条回答
  • 2021-02-07 14:39
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let v = ProgessView(frame: CGRect(x: 20, y: 200, width: 100, height: 10))
            view.addSubview(v)
    
            //v.progressLayer.strokeEnd = 0.8
    
        }
    }
    
    class ProgessView: UIView {
    
        lazy var progressLayer: CAShapeLayer = {
            let line = CAShapeLayer()
            let path = UIBezierPath()
            path.move(to: CGPoint(x: 5, y: 5))
            path.addLine(to: CGPoint(x: self.bounds.width - 5, y: 5))
            line.path = path.cgPath
            line.lineWidth = 6
            line.strokeColor = UIColor(colorLiteralRed: 127/255, green: 75/255, blue: 247/255, alpha: 1).cgColor
            line.strokeStart = 0
            line.strokeEnd = 0.5
            line.lineCap = kCALineCapRound
            line.frame = self.bounds
            return line
        }()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            backgroundColor = UIColor.white
            layer.cornerRadius = 5
            layer.borderWidth = 1
            layer.borderColor = UIColor(colorLiteralRed: 197/255, green: 197/255, blue: 197/255, alpha: 1).cgColor
            layer.addSublayer(progressLayer)
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    }
    

    Test my codes. You can design the height and the width as your want. You can use strokeEnd to change the progress of the progressView. You can add an animation to it. But actually, it is already animatable, you can change the value of the strokeEnd to see its primary effect. If you want to design your own animation. Try CATransaction like below.

    func updateProgress(_ progress: CGFloat) {
            CATransaction.begin()
            CATransaction.setAnimationDuration(3)
            progressLayer.strokeEnd = progress
            CATransaction.commit()
        }
    
    0 讨论(0)
  • 2021-02-07 14:39

    I had this exact same problem, which is what led me to your question after googling like crazy. The problem is two-fold. First, how to make the inside of the progress bar round at the end (which 季亨达's answer shows how to do), and secondly, how to make the round end of the CAShapeLayer you added match up with the square end of the original progress bar underneath (the answer to this other StackOverflow question helped with that How to get the exact point of objects in swift?) If you replace this line of code in 季亨达's answer:

    path.addLine(to: CGPoint(x: self.bounds.width - 5, y: 5))

    with this:

    path.addLine(to: CGPoint(x: (Int(self.progress * Float(self.bounds.width))), y: 5))

    you will hopefully get the result you're looking for.

    0 讨论(0)
  • 2021-02-07 14:40

    With swift 4.0 I'm doing in this way:

    let progressViewHeight: CGFloat = 4.0
    
    // Set progress view height
    let transformScale = CGAffineTransform(scaleX: 1.0, y: progressViewHeight)
    self.progressView.transform = transformScale
    
    // Set progress round corners
    self.progressView.layer.cornerRadius = progressViewHeight
    self.progressView.clipsToBounds = true
    
    0 讨论(0)
  • 2021-02-07 14:41

    Set line cap :

    .lineCap = kCALineCapRound;

    0 讨论(0)
  • 2021-02-07 14:44

    Yes ,one thing is missed...corner radius is set to progressview and it is reflecting as expected..

    But if you want your track image to be rounded you have to customise your progressview. You have to use image with rounded corner.

    [progressView setTrackImage:[UIImage imageNamed:@"roundedTrack.png"]];
    //roundedTrack.png must be of rounded corner
    

    This above code will help you to change image of trackView for your progressview.

    You may face the inappropriate stretching of image. You have to make your image resizable. May be the link below will be useful if issue arise https://www.natashatherobot.com/ios-stretchable-button-uiedgeinsetsmake/

    0 讨论(0)
  • 2021-02-07 14:47

    Another answer to throw in the mix, super hacky but very quick to use.

    You can just grab the sublayer and set its radius. No need to write your own UIProgressView or mess with clip paths.

    progressView.layer.cornerRadius = 5
    progressView.layer.sublayers[1].cornerRadius = 5
    progressView.subviews[1]. clipsToBounds = true
    progressView.layer.masksToBounds = true
    

    So you round the corner of your overall UIProgressView (no need for ClipsToBounds) Then the fill bar is the 2nd sublayer, so you can grab that and round its Corners, but you also need to set the subview for that layer to clipsToBounds.

    Then set the overall layer to mask to its bounds and it all looks good.

    Obviously, this is massively reliant on the setup of UIProgressView not changing and the 2nd subview/layer being the fill view.

    But. If you're happy with that assumption, super easy code wise to use.

    0 讨论(0)
提交回复
热议问题