自定义导航栏

33

我在 Dribble 上浏览时发现了附带的设计,想知道如何创建类似这样的自定义导航栏。我的意思是,如何创建一次导航栏并将其隐式地重用于每个视图控制器。

我考虑过创建一种根视图控制器并从其他视图控制器继承它,但我不知道该如何实现。

如果您有任何想法或链接,请告诉我!

谢谢。

Cyril

Nav bar image


我也想看看它是如何完成的! - tacos_tacos_tacos
这正是我当前项目所需要的。 - ajonnet
6个回答

8
由于iOS5的支持,不需要子类化或创建分类即可自定义UINavigationBar的外观。
以下代码块(将其放置在应用程序的applicationDidFinishLoading:方法中)将更改整个应用程序的UINavigationBar为您提供的任何图像。
请注意,这仅适用于iOS5。
但是,您还可以根据所处的视图控制器更改单个UINavigationBar的外观,方法是在viewDidLoad中使用以下代码。
上述代码仅讨论了由于iOS5而自定义UINavigationBar外观的新方法。但是,它并没有讨论如何实现按钮的方式。
然而,添加按钮是一项完全不同的工作。为此,建议子类化UINavigationBar,然后通过该方法添加所需的按钮。您甚至可以只使用标准的UINavigationBar,但使用特定视图运行的自定义UIBarButtonItem。
例如:
UIView *rightButton = [[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 30.0f, 30.0f)] autorelease];
[rightButton addSubview:[UIImage imageNamed:@"rightButtonImage.png"]];

UIBarButtonItem *rightButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:rightButton] autorelease];
[rightButtonItem setAction:@selector(rightButtonAction:)];

我没有测试过该代码,因此它不是一种复制/粘贴的解决方案,但它给了您一个实现“自定义”外观UIBarButtonItems所需做的事情的想法。

祝你好运!


6

在旧版 iOS 中,你需要子类化 UINavigationBar,例如:

@interface CustomNavigationBar : UINavigationBar
@end

@implementation CustomNavigationBar

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.opaque = YES;
        self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"CustomBackground"]];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    // Skip standard bar drawing
}

@end

要在您的视图控制器中使用自定义导航栏,您应该在XIB中将标准类名称更改为CustomNavigationBar

此外,您可以通过编程方式设置自定义导航栏:

UIViewController *tempController = [[[UIViewController alloc] init] autorelease];
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:tempController] autorelease];

NSData *archive = [NSKeyedArchiver archivedDataWithRootObject:navigationController];
NSKeyedUnarchiver *unarchiver = [[[NSKeyedUnarchiver alloc] initForReadingWithData:archive] autorelease];
[unarchiver setClass:[CustomNavigationBar class] forClassName:@"UINavigationBar"];
UINavigationController *customNavigationController = [unarchiver decodeObjectForKey:@"root"];

UIViewController *contentController = [[[ContentViewController alloc] init] autorelease];
customNavigationController.viewControllers = [NSArray arrayWithObject:contentController];

现在,customNavigationController 拥有了自定义的导航栏。

3

为NavigationBar设置自定义背景

UIImage *navBackground =[[UIImage imageNamed:@"navbarBackground"] 
                 resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[[UINavigationBar appearance] setBackgroundImage:navBackground forBarMetrics:UIBarMetricsDefault];

然后在您的视图控制器中为左、右边栏按钮和标题设置自定义视图。

self.navigationItem.titleView = customTitleView;
self.navigationItem.leftBarButtonItem = customBarButton;
self.navigationItem.rightBarButtonItem = customBarButton2;

我还有一个问题@eric-lars0n。我应该如何实际制作像图片中那样的导航按钮?我是否需要指定一个UI框架,大小与按钮的正方形相同,并将其添加为导航栏的子视图? - n00shie

1
你需要创建自己的UINavigationBar子类,并在需要navigationController的地方使用它。
在这个自定义类中,你将绘制背景、按钮、文本等。

更新

实际上,仔细观察这个例子,它似乎是一个UIToolBar。你可以将导航方法分配给按钮,如popViewController:等。对于"确认信息"和进度指示器,你可以使用标签和图片。对于右侧按钮,只需使用一个图形即可。

当然,你提供的示例只是一个概念,而不是一个实际的应用程序。但是通过一些创意、几小时的编程和几个小时的图形设计,你可以实现相同的界面。


3
事实上,这激励我编写一个自定义导航控制器。如果我成功实现了它,我会在 GitHub 上发布并更新链接。 - WrightsCS
UINavigationController类参考:“此类不适用于子类化。”但是,您可能会发现我在以下问题中的帖子有所帮助:https://dev59.com/tljUa4cB1Zd3GeqPQ2Ol - Luke
2
UINavigationBar的子类化,而不是控制器。 - WrightsCS
有趣,我真的需要看看你的实现才能理解它是如何工作的 :) - Cyril

0

您可以使用默认的UINavigationController并隐藏UINavigationBar。

然后,创建一个UIViewController的子类,其中包含所有导航元素和一个自适应大小的视图,用于放置内容。使所有的类都继承这个元素并绘制到视图中。按钮只需调用[self.navigationController popViewControllerAnimated:YES],视图中的UILabel只需将其文本设置为self.title即可。


我正在考虑基于这个的解决方案,创建一个自定义根视图控制器来管理自定义导航栏和动画,但我不知道如何在继承中使用它,有什么想法吗? - Cyril

0

使用Category,在您的委托文件(.m)中添加以下代码

@implementation UINavigationBar (UINavigationBarCategory)

- (void)drawRect:(CGRect)rect
{
    UIImage *navBg = [UIImage imageNamed:@"NavBar.png"];
    [navBg drawInRect:CGRectMake(0, 0, 320, 44)];
}
@end

编辑:

使用 Category 不是一个好的方式,我写了一个示例,不使用 Category,点击 这里


苹果工程师建议永远不要使用分类来自定义导航栏外观。 - Vadim
@SteveCotner 看一下我的编辑,我写了一个演示来自定义导航栏。在iOS5或以上版本中,使用分类的drawrect无法改变导航栏的外观,如果你像MFMailComposeViewController那样使用,它的外观看起来很丑。 - xda1001
谢谢。在iOS 5(和6...嘘...)中,我创建了一个类别并覆盖了sizeThatFits:以改变外观。我知道这有点hacky,因为它有时会在单个视图上调用多次。但到目前为止它一直有效,并使我免于在每个视图控制器中进行自定义。苹果不会因此拒绝应用程序,对吗? - Steve Cotner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接