UINavigationController with custom shape navigation bar

I am trying to create a custom UINavigationBar with a custom form like this (ignore transparency)

enter image description here

As you can see this UINavigationBar has a custom form and I am trying to replicate it.

Looking around I found this answer where it explains the first steps I followed.

1) I created a subclass of UINavigationBar called CustomNavigationBar. 2) I have overridden the sizeThatFits method as follows:

- (CGSize) sizeThatFits:(CGSize)size
{
  return CGSizeMake(320.0, 70.0);
}

      

3) And this is where I got lost ...

The previous answer said that UIBezierPath can be used to create a custom shape (even with curves) and then applied as a mask. I tried this overriding drawRect, but all I get is a big black navigation bar (my bar color is set to red).

EDIT: my draw was wrong, this is the correct option

- (void)drawRect:(CGRect)rect
{
  UIBezierPath *path = [[UIBezierPath alloc] init];
  [path moveToPoint:CGPointZero];
  [path addLineToPoint:CGPointMake(320.0, 0.0)];
  [path addLineToPoint:CGPointMake(320.0, 50.0)];
  [path addQuadCurveToPoint:CGPointMake(0.0, 50.0) controlPoint:CGPointMake(160.0, 90.0)];
  [path closePath];

  [[UIColor redColor] setFill];

  [path fill];
}

      

EDIT: As stated below, my code had some errors and is now drawing something.

enter image description here

As you can see, UIBezierPath detects the shape correctly, but there are some new problems:

1) The status bar is completely black, nothing shows up there, even if I change my color to light it shows nothing. What am I missing?

2) Because of the sizeThatFits method, the black part remains. Is there a way to make this part transparent?

Thanks everyone!

EDIT 2 : I've completely changed my point of view on this issue and I think I'm getting closer to a solution. Now I am trying to use a transparent png file as a background, but still need to increase its height, so this is my code right now.

- (CGSize) sizeThatFits:(CGSize)size
{
   return [[UIImage imageNamed:@"Layer3"] size];
}

- (void)drawRect:(CGRect)rect
{
  [self setClipsToBounds:NO];
  UIImage *image = [UIImage imageNamed:@"Layer3"];
  [image drawInRect:rect];
}

      

Easier, isn't it? Obviously "Layer3" is the name of my transparent png image. But now this is what I get.

enter image description here

As you can see, the status bar is not covered by the png image.

What am I missing now?

Thank!

+3


source to share


2 answers


Well I'm stupid xD

Finally I got a solution to this problem and it was much easier than I expected.

Here are the steps:

1) Subclass UINavigationBar, I created a CustomNavigationBar object.

2) Inside init, write these lines



UIImage *image = [UIImage imageNamed:@"barBackgroundImageName"];
[self setBackgroundImage:image forBarPosition:UIBarPositionTopAttached barMetrics:UIBarMetricsDefault];
[self setShadowImage:[UIImage new]];

      

This is important and the reason why I couldn't get it all to work, the image height should be 64px . I found out about this in Apple's online documentation , which describes the behavior of the UINavigationBar and the status bar.

3) And that's all. This is the result in my case (I know the background is not symmetrical, just a test).

enter image description here

Thank you all for your time and help !!!

+3


source


Hm, are you sure the panel has this shape, or is it just textured with a semi-transparent / transparent background with a rounded shape? I am asking you because as far as I know you cannot change the drawRect method from the UINavigationBar.

If it were me, I would take a gimp and make a rectangular background with the desired shape, using the alpha channel to achieve transparency. It's probably easier :)

EDIT: You might not want to give up your idea yet;) Check out https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/BezierPaths/BezierPaths.html and you will find that maybe , your code is still incomplete. In addition, a few little things:



  • You draw a curve up to the 180,100 point. Note that this is not the center of the bar, you must put 160 100 if you don't want it to be irregular. Also, you have to take care of this "320" from here. What if it works on iPad? What if it's a landscape? What if iOS 8 fits and the size is no larger than 320?;)

  • Observe also these "90" from above. As far as I know, the navbar is usually 44 pixels high (64 counting the status bar). The height is probably cropped to 64 somehow and you can't see the curve, so I would consider using a small number until you get it working.

EDIT 2: about your latest problems ... this is a crazy guess, but have you tried using the method [super drawRect:rect]

before you built the bezier path? The superclass has probably already implemented a drawing mechanism for the status bar / transparency and you just need to call it. Never done this in the past, so I don't know if this will work, but worth a try;)

EDIT 3: About the status bar issue, have you tried to implement this protocol? https://developer.apple.com/library/ios/documentation/uikit/reference/UIBarPositioning_Protocol/Reference/Reference.html#//apple_ref/c/econst/UIBarPositionTop This is another crazy guess as I haven't done this before. but it looks like UINavigationBar implements the UIBarPositioning protocol where you can implement barPosition

make it return a value UIBarPositionTopAttached

and that way your navbar will be displayed in the status bar. If so, then probably the only remaining step is to make it 20px higher and add a 20px vertical offset to all views. Worth a try I think!;)

0


source







All Articles