【问题标题】:UINavigationController with custom shape navigation Bar带有自定义形状导航栏的 UINavigationController
【发布时间】:2014-10-23 12:29:39
【问题描述】:

我正在尝试使用自定义形状创建自定义 UINavigationBar,如下所示(忽略透明度)

如您所见,此 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];
}

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

如您所见,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 图像的名称。但现在,这就是我得到的。

如您所见,状态栏没有被 png 图片覆盖。

我现在错过了什么?

谢谢!

【问题讨论】:

  • 到目前为止你还没有画任何东西。您创建了一个 BezierPath,但您没有绘制它。
  • 这个人完全正确 ;) 查看官方文档的这一部分:developer.apple.com/library/ios/documentation/2ddrawing/… Search for "Rendering the Contents of a Bézier Path Object"
  • 谢谢两位。我修改了我的代码,现在画了一些东西,但仍然存在一些问题。我和他们一起编辑了我的问题。谢谢。

标签: ios objective-c iphone ios7 uinavigationbar


【解决方案1】:

好吧,我很傻xD

最后我找到了解决这个问题的方法,它比我预期的要简单得多。

步骤如下:

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

2) 在它的 init 里面,写下这几行

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

这很重要,也是我无法让这一切工作的原因,图像的高度必须为 64 像素。我在 online Apple Documentation 上找到了这个,它描述了 UINavigationBar 和状态栏之间的行为。

3) 仅此而已。这是我的结果(我知道背景不是对称的,只是一个测试)。

感谢大家的时间和帮助!!!

【讨论】:

    【解决方案2】:

    嗯,您确定该条具有这种形状,或者它只是带有圆形的半透明/透明背景纹理?我问你是因为据我所知,你不能改变 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:关于您的最后一个问题...这是一个疯狂的猜测,但是您是否尝试过在构建贝塞尔路径之前调用 [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 像素,并为所有视图添加 20 像素的垂直偏移。值得一试,我猜! ;)

    【讨论】:

    • 谢谢,我对我的代码和我的问题做了一些修改。出现了一些新问题:S
    • 已更新。让我们看看我们是否幸运!
    • 试过了,但什么也没做 :( 我正在尝试另一个视角,使用透明的 png 文件作为导航栏的背景。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多