带有自定义形状导航栏的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的垂直偏移量。 值得一试,我猜! ;)