自定义UINavigationBar返回按钮且不带标题

238

如何在iOS 7及以上版本中定制没有标题的返回导航按钮?(即只有箭头)

self.navigationItem.leftBarButtonItem = self.editButtonItem;

我只是想知道他们是否有任何self.backButtonItem; 或者类似这样的东西?

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
                   initWithBarButtonSystemItem:UIBarButtonSystemItemBACK 
                   target:self action:@selector(back)];

3
您可以使用 @hiroshi 的答案和导航栏 tintColor 属性来制作自定义颜色的 chevron(矢车菱形符号),而且没有任何标题。 - Dmitry Zhukov
对于那些拥有选项卡栏的用户,如果您不想要返回按钮的文本,则可以在TabBarController的**viewDidLoad()**中添加以下代码进行修复:self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) - Borzh
36个回答

318

这其实很简单,我是这样做的:

Objective C

// Set this in every view controller so that the back button displays back instead of the root view controller name
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

Swift 2

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)

Swift 3

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

将这行代码放到推入堆栈的视图控制器 (上一个视图控制器) 中。新推入的视图控制器的返回按钮现在将显示你为 initWithTitle 放置的任何内容,此处为空字符串。


3
我用了这个,但标题以动画方式出现和消失? - user1010819
7
谢谢 Kyle!我一直在寻找一种方法来重命名iOS 7中的默认返回按钮。我将这个代码放在我的视图控制器的prepareForSegue方法里,它完美地工作了。 - yiwei
1
@user1010819 这是预期的行为,当切换视图控制器时,barButtonItems 将会以动画方式进入和退出。您想要实现什么? - Kyle Begeman
1
@YiweiGao 没问题!只要你知道正确的代码,这只是另一件相当简单的事情!我很高兴它能帮到你! - Kyle Begeman
3
我觉得这需要进行更新,现在什么也没有显示出来,箭头默认情况下不在那里吗? - Mathijs Segers
显示剩余7条评论

196

我找到了一个简单的方法来制作iOS单向箭头的返回按钮。

假设您有一个导航控制器从ViewB跳转到ViewA。在IB中,选择ViewA的导航栏,您应该看到这些选项:标题,提示和返回按钮。

ViewA导航栏选项

ViewA navigate bar options

技巧是在上一个视图控制器(View A)的选项中选择您要返回的目标视图控制器(View B)的返回按钮标题。如果您不填写“返回按钮”选项,iOS将自动将标题设置为“返回”,并使用上一个视图控制器的标题。所以,您需要用一个空格填充此选项。

在“返回按钮”选项中填充空格

Fill space in "Back Button" option

结果:

The Result:


欢迎来到[so]。如果您还没有了解我们的情况,请查看一下我们的介绍,并阅读一些关于我们工作方式和社区习俗的帮助文章。如果您需要任何有关网站功能的帮助,请不要害怕搜索,然后在[meta]上提出问题(如果您仍然找不到答案)。谢谢,祝好运!无论如何,现在您可以发布您的图片了... :) - Qantas 94 Heavy
53
它可以工作,只需注意 - 您需要为上一个控制器(例如导航控制器中的rootViewController)设置“返回按钮”。 - evfemist
确保在ViewA的导航项中,"hidesBackButton"未设置为TRUE。 - shim
1
对我来说,只有当源视图控制器和目标视图控制器的 NavigationItem 都将 Back Button 设置为一个空格字符时(即 ViewA 和 ViewB 都是如此),它才能正常工作。 - dcestari
对我来说,在 iOS 11 上在 目标视图控制器 中定义它就足够了。 - kiecodes
显示剩余3条评论

77

只需使用图片!

OBJ-C:

- (void)viewDidLoad {
     [super viewDidLoad];
     UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"Icon-Back"]
                                                                                        style:UIBarButtonItemStylePlain
                                                                                       target:self.navigationController
                                                                                       action:@selector(popViewControllerAnimated:)];
     self.navigationItem.leftBarButtonItem = backButton;
}

SWIFT 4:

let backBTN = UIBarButtonItem(image: UIImage(named: "Back"), 
                              style: .plain, 
                              target: navigationController, 
                              action: #selector(UINavigationController.popViewController(animated:)))
navigationItem.leftBarButtonItem = backBTN
navigationController?.interactivePopGestureRecognizer?.delegate = self

Icon-Back.png

Icon-Back

Icon-Back@2x.png

Icon-Back@2x

Icon-Back@3x.png

Icon-Back@23x


5
使用这种解决方案似乎会失去“滑动返回”功能。 - j7nn7k
17
这段代码可以实现保持向右滑动返回手势。 - Victor Carmouze
我一直在寻找这个答案,或许是我一生中的全部,即动作选择器。 - Des

29

iOS7有新的界面规则,所以在推送UIView时最好保留至少后退箭头。很容易通过在推送视图之前添加以下代码(或者如果你正在使用StoryBoards,可以在prepareForSegue中添加)来动态更改“返回”文本:

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
      self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"NEW TITLE" style:UIBarButtonItemStylePlain target:nil action:nil];
}

这将更改默认的“返回”文本,但会保留iOS7样式的返回箭头。 您还可以在推送视图之前更改返回箭头的色调:

- (void)viewDidLoad{
     //NavBar background color:
     self.navigationController.navigationBar.barTintColor=[UIColor redColor];
//NavBar tint color for elements:
     self.navigationController.navigationBar.tintColor=[UIColor whiteColor];
}

希望这能为你提供帮助!


2
这个方法非常有效,似乎比其他选项更好。例如,与其他答案不同,标题永远不需要重置为先前的值。 - pr1001

26

你不需要做太多事情。你可以通过Storyboard实现相同的效果。

只需进入根导航控制器并添加一个空格即可。请记住,不是针对你想要没有标题的后退按钮的那个控制器,而是针对根导航控制器。

根据下面的图像。这适用于iOS 7和iOS 8


我已经尝试过了,它可以运行。 但是我仍然无法在代码中更改标题。 - Yu-Lin Wang
之前使用 XCode7 可以正常工作,但在 XCode8 -> ios10.X 之后不再可用。我使用了 @iwasrobbed 的方法。 - LucioB
所有的天才都是简单的! - Illya Krit

22

虽然Kyle Begeman的答案完全能解决问题,但是在每个可能需要的视图控制器中都使用这段代码还是相当烦人的。我最终使用了一个简单的UINavigationItem类别。注意,这里有危险!不好意思,我是说,这里有方法交换:

#import <objc/runtime.h>

@implementation UINavigationItem (ArrowBackButton)

static char kArrowBackButtonKey;

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method m1 = class_getInstanceMethod(self, @selector(backBarButtonItem));
        Method m2 = class_getInstanceMethod(self, @selector(arrowBackButton_backBarButtonItem));
        method_exchangeImplementations(m1, m2);
    });
}

- (UIBarButtonItem *)arrowBackButton_backBarButtonItem {
    UIBarButtonItem *item = [self arrowBackButton_backBarButtonItem];
    if (item) {
        return item;
    }

    item = objc_getAssociatedObject(self, &kArrowBackButtonKey);
    if (!item) {
        item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:NULL];
        objc_setAssociatedObject(self, &kArrowBackButtonKey, item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return item;
}

@end

1
我点了赞,但后来决定使用一个更简单的方法 -- [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000, -1000) forBarMetrics:UIBarMetricsDefault]; (来源) -- 这可能不太优雅,但交换方法感觉有些过度。 - dmur
2
各位认真点...不要考虑其他解决方案。实现@nicky发布的类别解决方案,不要犹豫。如果您添加这个Prefix.pch文件,这是一个可以在整个应用程序中重复使用的好解决方案。苹果鼓励使用类别将方法添加到现有类,尽可能利用它。 - zmonteca
这是我认为最好的解决方案,不过 "method_exchangeImplementation" 有点不安全,请看一下这个:正确的方法交换 和这个 NSHipster 方法交换指南 - Alessandro Orrù
@AlessandroOrrù 在这种情况下,这应该是安全的,因为交换方法是 UINavigationItem 自己的方法,没有涉及继承。而且 _cmd 很不可能在 getter 中使用。无论如何,这是一个很好的观点。所以,如果您的项目中有任何这些众多的交换助手,请确保在此处也使用它。 - secondcitysaint

22

这个方法可以使用,但是如果你返回到前一个元素,它会删除前一个元素的标题:

self.navigationController.navigationBar.topItem.title = @"";

只需在推送视图控制器的 viewDidLoad 中设置此属性即可。


17
即使你返回到之前的项目,这将删除先前项目的标题。不太好:( - Antzi
我在 viewWillAppear 中设置了推送 VC 的标题,以便始终正确设置。 - Guto Araujo
@GutoAraujo 它可以工作,但标题会延迟1到2秒重新出现,这使得用户体验不那么好。 - fuiiii
在xCode8 -> ios10.X中,这似乎是解决问题的唯一方法。 - LucioB

21

编辑:2014年04月09日:随着我的声望提高,我感到抱歉,因为我不再使用这个技巧。我建议使用Kyle的答案。此外请注意,self.navigationItem.backBarButtonItemself并不是显示返回按钮的视图控制器,而是要返回的上一个视图控制器。

如果您不需要为前一个视图控制器设置标题文本,请将标题填充为空字符串;

self.navigationItem.title = @"";
[self.navigationController pushViewController:viewController animated:YES];

这将防止推出的视图控制器上显示带有尖角符号的“返回”按钮。

编辑:即使您使用非空白标题文本,在viewWillAppear:中设置上一个视图控制器的标题也有效,但当视图控制器弹出时,标题可能会在闪烁中闪烁。我认为“Twitter应用程序”似乎进行了更微妙的骇客攻击,以避免闪烁。


我在这里遇到的唯一问题是,当我点击导航栏返回时,上一个视图的标题变为空白。有什么解决办法吗? - Alioo
@Alioo,你试过我在“EDIT”行提到的方法了吗? - hiroshi

12

这是我做的方式,也是最简单、可行和最清晰的方法。

如果嵌入到导航控制器上,则可以起作用。

Swift 3

viewDidLoad中,将此代码添加到您想要返回按钮只为箭头的视图控制器中。

if let topItem = self.navigationController?.navigationBar.topItem {
   topItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
这个与 @Kyle Begeman 的回答的不同之处在于,你需要在想要返回按钮仅为箭头的视图控制器上调用此方法,而不是在推送堆栈视图控制器上调用。

7

目标:UINavigationBar上所有返回按钮定制为白色图标。

步骤: 1. 在AppDelete的“didFinishLaunchingWithOptions”方法中:

UIImage *backBtnIcon = [UIImage imageNamed:@"navBackBtn"];


if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    [UINavigationBar appearance].tintColor = [UIColor whiteColor];
    [UINavigationBar appearance].backIndicatorImage = backBtnIcon;
    [UINavigationBar appearance].backIndicatorTransitionMaskImage = backBtnIcon;
}else{

    UIImage *backButtonImage = [backBtnIcon resizableImageWithCapInsets:UIEdgeInsetsMake(0, backBtnIcon.size.width - 1, 0, 0)];
    [[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage  forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -backButtonImage.size.height*2) forBarMetrics:UIBarMetricsDefault];
}

2.在通用超级ViewController类的viewDidLoad方法中:

 if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@""
                                                                     style:UIBarButtonItemStylePlain
                                                                    target:nil
                                                                    action:nil];
        [self.navigationItem setBackBarButtonItem:backItem];
    }else{
        //do nothing
    }

该警告表明,在C99中,“SYSTEM_VERSION_”的隐式版本无效。 - Jayprakash Dubey

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