0
votes

enter image description here

Hi All, trying make a custom progress view which look like this:

But getting lot of warning when set progreessView.progress = 0.25 Can any one look at this code and tell me whats wrong, Also the current code not seems to be best to achieve this.. welcome to other ideas also.

hope we don't need to set the stroke.

this is the source code:

class MyProgressView: UIView {
    var progress: CGFloat = 0.5 {
        didSet {
            setProgress()
        }
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    func setup() {
        self.backgroundColor = UIColor.clear
    }
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        setProgress()
    }
    func setProgress() {
        var progress = self.progress
        progress = progress > 1.0 ? progress / 100 : progress

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

        let width = self.frame.width
        let height = self.frame.height

        let bgPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width, height: height), cornerRadius: height / 2.0)
        UIColor.gray.setFill()
        bgPath.fill()
        //UIColor.clear.setStroke()
        //bgPath.stroke()
        bgPath.close()

        let width2 = self.frame.width * progress
        let highlightPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: width2, height: height), cornerRadius: height / 2.0)
        UIColor.red.setFill()
        highlightPath.fill()
        highlightPath.close()

        let gapPath1 = UIBezierPath(rect: CGRect(x: width/4-2, y: 0, width: 2, height: height))
        UIColor.white.setFill()
        gapPath1.fill()
        gapPath1.close()

        let gapPath2 = UIBezierPath(rect: CGRect(x: width/2-2, y: 0, width: 2, height: height))
        UIColor.white.setFill()
        gapPath2.fill()
        gapPath2.close()

        let gapPath3 = UIBezierPath(rect: CGRect(x: width*3/4-2, y: 0, width: 2, height: height))
        UIColor.white.setFill()
        gapPath3.fill()
        gapPath3.close()

        self.setNeedsDisplay()
    }
}

Warnings startes with:

CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. May 18 13:34:13 [7500] : CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. May 18 13:34:13 [7500] : CGContextSetFlatness: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

2
Your progress will be only segment by segment right?? not continuous..elk_cloner
segment by segment. thanks to looking into this.jpulikkottil

2 Answers

1
votes

CGContextSetFillColorWithColor: invalid context 0x0.

This means you're trying to do core graphics drawing operations without a valid drawing context. 0x0 is nil.

You'll get this output whenever you try to fill or stroke paths when there is no current graphics context.

There is only a current graphics context when you've made one yourself, which would be for drawing images offscreen, or when UIKit makes one, which it does before it calls draw(_ rect:)

You call setProgress() from within draw(_ rect:), in those cases your drawing will work and not throw errors, though you need to remove the setNeedsDisplay call from the end as this will just cause the drawing to happen again and again.

However, you also call it from within the property observer (didSet under progress). Instead of calling that drawing code directly, which isn't going to have a context and so will give you console warnings instead of drawing, you should just call setNeedsDisplay in the property observer.

0
votes

You wanted other idea.So here is my idea and i already did this. I used auto-layout and UiKit animation for custom progress.

How: I have increased the width of progress(A View) according to my predefined time.Say when 25% download is done i have increased the width 25% and this increment has been put in UIview animation for smooth effect. And ofcourse,

self.layoutIfneeeded()

does the trick.You can find lots of example of how this animation be done. :)