0

I need help with drawing something like this: enter image description here

I have been told that the gray background bar and the purple bar should be drawn on separate layers. And then the dots there that signifies the chapters of a book (which this slider is about) will be on a layer on top of those two.

I have accomplished the task of creating the gradient on the active bar and drawing it like so:

- (void)drawRect:(CGRect)rect{
    self.opaque=NO;

    CGRect viewRect = self.bounds;
    //NSLog(@"innerRect width is: %f", innerRect.size.width);
    CGFloat perPageWidth =  viewRect.size.width/[self.model.book.totalPages floatValue];
    NSLog(@"perpage width is: %f", perPageWidth);
    CGContextRef context = UIGraphicsGetCurrentContext();

    UIBezierPath *beizerPathForSegment= [UIBezierPath bezierPath];

    NSArray *arrayFromReadingSessionsSet =[self.model.readingSessions allObjects];
    NSArray *arrayFromAssesmentSet = [self.model.studentAssessments allObjects];
    NSLog(@"array is : %@", self.model.readingSessions);

    CGGradientRef gradient = [self gradient];



    for (int i=0;i<[arrayFromReadingSessionsSet count]; i++) {

        ReadingSession *tempRSObj= [arrayFromReadingSessionsSet objectAtIndex:i];
        CGFloat pageDifference = [tempRSObj.endPage floatValue]-[tempRSObj.startPage floatValue];
        NSLog(@"startpage is: %@, end page is: %@, total pages are: %@", tempRSObj.startPage, tempRSObj.endPage, self.model.book.totalPages) ;


        CGRect ProgressIndicator = CGRectMake(perPageWidth*[tempRSObj.startPage floatValue], viewRect.origin.y, perPageWidth*pageDifference, viewRect.size.height);


       [beizerPathForSegment appendPath:[UIBezierPath bezierPathWithRoundedRect:ProgressIndicator cornerRadius:13.0]];
}
[beizerPathForSegment addClip];

    CGContextDrawLinearGradient(context, gradient, CGPointMake(CGRectGetMidX([beizerPathForSegment bounds]), CGRectGetMaxY([beizerPathForSegment bounds])),CGPointMake(CGRectGetMidX([beizerPathForSegment bounds]), 0), (CGGradientDrawingOptions)NULL);
}

How do I shift it onto a layer and then create another layer and another layer and then put them over one another?

TIA

Anton Unt
  • 1,835
  • 1
  • 21
  • 47

1 Answers1

1

I’m guessing the person you spoke with was referring to CALayer. In iOS, every view has a CALayer backing it. Instead of implementing -drawRect: in your view, do this:

  1. link with QuartzCore
  2. #import <QuartzCore/QuartzCore.h> anywhere you want to use this.
  3. Use to your view’s layer property.

Layers behave a lot like views, in that you can have sublayers and superlayers, and layers have properties for things like background color, and they can be animated. A couple of subclasses that will probably be useful for your purposes are CAGradientLayer and CAShapeLayer. For more on how to use layers, refer to the Core Animation Programming Guide.

Community
  • 1
  • 1
Zev Eisenberg
  • 8,080
  • 5
  • 38
  • 82
  • I can't make a lot of changes to this code. It's actually quite tweaked to the needs and the gradient has to be the CG one because of the smoothness. Is there a way I can do this on just one layer? The whole CG thing, that is? – Anton Unt Nov 26 '12 at 15:53
  • You could port your existing code to CALayer’s [`-drawInContext:`](https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instm/CALayer/drawInContext:) method, but that would defeat the purpose of doing this with layers, which use GPU-based compositing for better performance without having to keep redrawing your graphics by hand. However, for something simple like this, `-drawRect:` might be appropriate. – Zev Eisenberg Nov 26 '12 at 16:51
  • Just remember to use the `(CGRect)rect` parameter of `-drawRect:`, in conjunction with `[UIView setNeedsDisplayInRect:]`, to only redraw the portions of your view that have changed. – Zev Eisenberg Nov 26 '12 at 16:52
  • Thanks for the reply, Zev. I am very new to the drawing thing itself. Can you help me a little with an example? Creating a layer then drawing on it and then creating another layer over it and drawing over it, that is. I know I might be asking for too much but I am really hoping here! – Anton Unt Nov 27 '12 at 07:00
  • Also, I know we can place one layer over another but how do we actually do the drawing like it's done in the code over there just for a specific layer. One or two lines of code from my snippet converted into the layered kind for that would be enough. – Anton Unt Nov 27 '12 at 07:04
  • You should be able to do most or all of what is in your screenshot without custom drawing. Just make some `CAGradientLayer`s and set the `cornerRadius` property. Add the layers as sublayers of a view’s layer. Here’s a [decent tutorial](http://danielbeard.wordpress.com/2012/02/25/gradient-background-for-uiview-in-ios/) to get you started with CAGradientLayer. – Zev Eisenberg Nov 27 '12 at 21:22
  • Oh, and here’s a good [Introduction to CALayers Tutorial](http://www.raywenderlich.com/2502/introduction-to-calayers-tutorial) that includes custom drawing in layers, which I haven’t used enough to authoritatively write any code on it. – Zev Eisenberg Nov 27 '12 at 21:24