UINavigationController与自定义形状导航栏

时间:2014-08-29 13:23:01

标签: ios objective-c iphone ios7 uinavigationbar

我尝试使用自定义形状创建自定义UINavigationBar(忽略透明度)

enter image description here

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

环顾四周,我发现了this response,它解释了我遵循的第一步。

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

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

3)这就是我失去的地方......

在前面的回答中说UIBezierPath可用于创建自定义形状(即使是曲线),然后应用为蒙版。我试过这个覆盖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];
}

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

enter image description here

如您所见,UIBezierPath正确定义了形状,但是存在一些新问题:

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

2)由于sizeThatFits方法,还剩下一些黑色部分。有没有办法让这部分透明?

感谢所有人!

编辑2 :好吧,我完全改变了对这个问题的看法,我认为我已经接近解决方案了。现在我尝试使用透明的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图像的名称。但现在,这就是我所得到的。

enter image description here

如您所见,状态栏未包含在png图像中。

我现在缺少什么?

谢谢!

2 个答案:

答案 0 :(得分:5)

嗯,我很傻xD

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

以下是步骤:

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

2)在它的init中,写下这行

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

这很重要,也是我无法完成所有这些工作的原因,图片的高度必须为64px 。我在online Apple Documentation上找到了它,它描述了UINavigationBar和状态栏之间的行为。

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

enter image description here

感谢您的所有时间和帮助!!!

答案 1 :(得分:0)

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

如果是我,我会拿起gimp并制作一个具有所需形状的矩形背景,使用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:关于你的最后一个问题......这是一个疯狂的猜测,但你是否尝试在建立bezier路径之前调用[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方法,强制它返回{{ 1}}值,这样导航栏将显示在状态栏下方。如果是这样,那么可能唯一剩下的步骤是使其高出20个像素,并为所有视图添加20px垂直偏移。值得一试,我想! ;)