Search code examples
objective-cios4streaminguislideruiprogressview

UISlider with ProgressView combined


Is there an apple-house-made way to get a UISlider with a ProgressView. This is used by many streaming applications e.g. native quicktimeplayer or youtube. (Just to be sure: i'm only in the visualization interested)

Slider  with loader

cheers Simon


Solution

  • Here's a simple version of what you're describing.

    alt text

    It is "simple" in the sense that I didn't bother trying to add the shading and other subtleties. But it's easy to construct and you can tweak it to draw in a more subtle way if you like. For example, you could make your own image and use it as the slider's thumb.

    This is actually a UISlider subclass lying on top of a UIView subclass (MyTherm) that draws the thermometer, plus two UILabels that draw the numbers.

    The UISlider subclass eliminates the built-in track, so that the thermometer behind it shows through. But the UISlider's thumb (knob) is still draggable in the normal way, and you can set it to a custom image, get the Value Changed event when the user drags it, and so on. Here is the code for the UISlider subclass that eliminates its own track:

    - (CGRect)trackRectForBounds:(CGRect)bounds {
        CGRect result = [super trackRectForBounds:bounds];
        result.size.height = 0;
        return result;
    }
    

    The thermometer is an instance of a custom UIView subclass, MyTherm. I instantiated it in the nib and unchecked its Opaque and gave it a background color of Clear Color. It has a value property so it knows how much to fill the thermometer. Here's its drawRect: code:

    - (void)drawRect:(CGRect)rect {
        CGContextRef c = UIGraphicsGetCurrentContext();
        [[UIColor whiteColor] set];
        CGFloat ins = 2.0;
        CGRect r = CGRectInset(self.bounds, ins, ins);
        CGFloat radius = r.size.height / 2.0;
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, CGRectGetMaxX(r) - radius, ins);
        CGPathAddArc(path, NULL, radius+ins, radius+ins, radius, -M_PI/2.0, M_PI/2.0, true);
        CGPathAddArc(path, NULL, CGRectGetMaxX(r) - radius, radius+ins, radius, M_PI/2.0, -M_PI/2.0, true);
        CGPathCloseSubpath(path);
        CGContextAddPath(c, path);
        CGContextSetLineWidth(c, 2);
        CGContextStrokePath(c);
        CGContextAddPath(c, path);
        CGContextClip(c);
        CGContextFillRect(c, CGRectMake(r.origin.x, r.origin.y, r.size.width * self.value, r.size.height));
    }
    

    To change the thermometer value, change the MyTherm instance's value to a number between 0 and 1, and tell it to redraw itself with setNeedsDisplay.