带有自定义形状导航栏的UINavigationController

我想创build一个自定义的UINavigationBar与自定义形状,像这样(忽略透明度)

在这里输入图像说明

正如你所看到的,这个UINavigationBar有一个自定义的形状,我试图复制它。

环顾四周,我发现了这个答案 ,它解释了我所遵循的第一步。

1)我创build了一个名为CustomNavigationBar的UINavigationBar的子类。 2)我覆盖sizeThatFits方法是这样的:

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

3)这里是我迷路的地方

在前面的答案中说的是UIBezierPath可以用来创build一个自定义的形状(即使有曲线),然后作为一个面具应用。 我试过这个重写drawRect,但我得到的是一个大的黑色导航栏(我的栏颜色设置为红色)。

编辑:我的画是错的,这是正确的

 - (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]; } 

编辑:如下所述,我的代码有一些错误,现在它画了一些东西。

在这里输入图像说明

正如你所看到的,UIBezierpath正确地定义了形状,但是还有一些新的问题:

1)状态栏是完全黑色的,没有任何东西在那里呈现,即使我改变他的颜色为光,它不显示任何东西。 我错过了什么?

2)由于sizeThatFits方法,还剩下一些黑色的部分。 有什么方法可以使这个部分透明吗?

谢谢大家!

编辑2 :嗯,我完全改变了我对这个问题的看法,我想我正在接近一个解决scheme。 现在我试图使用透明PNG文件作为背景,但仍然需要增加它的高度,所以现在这是我的代码。

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

更简单,对吧? 显然“Layer3”是我的透明PNG图像的名称。 但现在,这正是我所得到的。

在这里输入图像说明

正如你所看到的,状态栏没有被png图像覆盖。

我现在失去了什么?

谢谢!

那么,我很傻xD

最后我得到了这个问题的解决scheme,这比我想象的要简单得多。

这里是步骤:

1)UINavigationBar子类,我创build了一个CustomNavigationBar对象。

2)在init的内部,写下这行

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

这是重要的,也是为什么我无法做到这一切的原因, 图像的高度必须是64px 。 我在在线的Apple文档中find了这个描述UINavigationBar和状态栏之间行为的地方。

3)就这样。 这是我的结果(我知道背景是不对称的,只是一个testing)。

在这里输入图像说明

感谢所有的时间和帮助!

嗯,你确定酒吧有这个形状,还是只是它的半透明/透明的背景与圆形纹理? 我问你,因为,据我所知,你不能改变从UINavigationBar的drawRect方法。

如果是我,我会拿起芯片,并用所需的形状做一个长方形的背景,使用alpha通道来实现透明度。 这可能更容易:)

编辑:也许你不应该放弃你的想法呢;)检查这个https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/BezierPaths/BezierPaths.html ,你会发现也许你的代码还不完整。 另外,还有一些小事情:

  • 你正在把曲线拉到180,100点。 请注意,这不是酒吧的中心,如果你不想让酒吧变得不规则,你应该投入160,100。 此外,你应该从这里关心那些“320”的。 如果在iPad上运行呢? 如果是风景呢? 如果iOS 8来了,尺寸不再是320呢? ;)

  • 从高处也要注意这些“90”。 据我所知,导航栏通常是44像素高(64个状态栏)。 这个高度很可能会以某种方式被修整为64,并且你不会看到曲线,所以我会考虑使用一个小数字,直到它有效。

编辑2:关于你最后的问题…这是一个疯狂的猜测,但你有没有尝试甚至在build立贝塞尔path之前调用[super drawRect:rect]方法? 超类可能已经实现了状态栏/透明的绘画机制,你只需要调用它。 从来没有做过,所以我不知道它是否会工作,但值得一试;)

编辑3:关于状态栏的问题,你有没有尝试过实现这个协议? https://developer.apple.com/library/ios/documentation/uikit/reference/UIBarPositioning_Protocol/Reference/Reference.html#//apple_ref/c/econst/UIBarPositionTop这是另一个疯狂的猜测,因为我以前没有做过,但是它看起来像UINavigationBar实现了UIBarPositioning协议,在这里你可以实现barPosition方法,强制它返回UIBarPositionTopAttached值,这样你的导航栏将显示在状态栏下。 如果是这样的话,那么可能唯一剩下的步骤是使其高出20个像素,并向所有视图添加20px的垂直偏移量。 值得一试,我猜! ;)