1

I tried to draw a custom UINavigationBar via drawRect on iOS7. With the changes of the Navigationbar and the Statusbar my draw begins on y-origin 20.0, not on my 0.0 behind the Statusbar. I checked the wwdc videos but I only found examples with images not with custom draw. Any ideas? Do I need to set some parameters in my subclass?

  1. create a new project based on "Master-Detail Application"
  2. create a sublass for UINavigationBar
  3. change the UINavigationBar in Main.storyboard to the custom class
  4. turn off translucent [self setTranslucent:NO];
  5. add a real simple drawRect to the sublass of UINavigationBar

I made a simple test:

CGColorSpaceRef colorSpace  = CGColorSpaceCreateDeviceRGB();
UIBezierPath* maskPath = [UIBezierPath bezierPathWithRect: CGRectMake(0, 0, 320, 64)];

[maskPath closePath];
[[UIColor greenColor] setFill];
[maskPath fill];

CGColorSpaceRelease(colorSpace); 

The green NavigationBar begins under the Statusbar, how can I draw by starting behind the Statusbar?

CURRENT SOLUTION:

@Redwarp posted one way, I made also a simple version to test:

CustomBGView *testView = [[CustomBGView alloc] initWithFrame:CGRectMake(0, 0, 320, 64)];

RetinaAwareUIGraphicsBeginImageContext(testView.frame.size);

CGContextRef context = UIGraphicsGetCurrentContext();
[testView.layer renderInContext:context];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[self setBackgroundImage:image forBarPosition:UIBarPositionTop barMetrics:UIBarMetricsDefault];

Inside the custom UIView you can draw like you want and your custom view appears also behind the StatusBar.

iOSNerd
  • 31
  • 4
  • Did you find a solution ? I didn't understand why your question was down-voted. I have exactly the same problem. – Redwarp Oct 10 '13 at 13:59
  • I'm also confused about the down-vote... Anyway, I have not found a solution right now @Redwarp. I hope/wish/bet you can set an attribute and you will be able to draw a custom navigationbar style with drawRect behind the statusbar. But maybe I missed another way? – iOSNerd Oct 11 '13 at 09:46

1 Answers1

4

I found a solution, which is a bit peculiar : I subclass the UINavigationBar, and in the onLayoutSubviews, I create the background I want to create, and set it as background image. So I do the equivalent of the drawRect, but in a UIImage that I set as background. Then, in the xib or storyboard, I select my subclass as the type of the Navigation bar.

Here goes :

@implementation MyNavigationBar

- (void)layoutSubviews {
    [super layoutSubviews];

    CGPoint origin = [self.superview convertPoint:self.frame.origin toView:nil];
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.bounds.size.width, self.bounds.size.height + origin.y), NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClipToRect(context, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height + origin.y));
    [self.baseImage drawInRect:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [self setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
    // If you don't want the bar shadow, set the shadow image as null
    [self setShadowImage:[UIImage new]];
}

And whenever you wan't to change the image, you call [navigationBar needsLayout], and it will call layoutSubviews again

EDIT : The trick is getting the origin of the nav bar. If there is a status bar, the origin will be of y 20. If no status bar, it will be 0. So you add the origin.y to the height of the image your drawing into, and you will have a nice result.

Redwarp
  • 3,221
  • 3
  • 31
  • 44
  • I wish I could vote up you post. I will wait until next week before I will accept your solution. Maybe someone have a second way!? – iOSNerd Oct 11 '13 at 13:34
  • Okay! I meant "I subclass the UINavigation bar", not "I subclass the subview" <- edited – Redwarp Oct 11 '13 at 13:50