What I wanted to do is to remove the text from the 'Back' button of a UIBarButtonItem
, leaving only the blue chevron on the navigation bar. Keep in mind that I'm developing for iOS 7. I've tried several methods, including, but not limited to:
This is the image method which I did not like (the image looked out of place):
UIBarButtonItem *barBtnItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"iOS7BackButton"] style:UIBarButtonItemStylePlain target:self action:@selector(goToPrevious:)];
self.navigationItem.leftBarButtonItem = barBtnItem;
Another method I tried was this, which simply did not work (nothing was displayed):
UIBarButtonItem *barBtn = [[UIBarButtonItem alloc]init];
barBtn.title=@"";
self.navigationItem.leftBarButtonItem=barBtn;
What I wanted to achieve is something like the back buttons found in the iOS 7 Music app, which only featured a single chevron.
Thanks.
This question is related to
ios
uinavigationbar
uibarbuttonitem
uinavigationitem
I create a custom class for UINavigationController
and apply it to all of the navigation controllers in my app. Inside this custom UINavigationController
class I set the UINavigationBar
delegate to self
once the view loads.
- (void)viewDidLoad {
self.navigationBar.delegate = self;
}
Then I implement the delegate method:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item {
// This will clear the title of the previous view controller
// so the back button is always just a back chevron without a title
if (self.viewControllers.count > 1) {
UIViewController *previousViewController = [self.viewControllers objectAtIndex:(self.viewControllers.count - 2)];
previousViewController.title = @"";
}
return YES;
}
This way I simply assign my custom class to all my navigations controllers and it clears the title from all the back buttons. And just for clarity, I always set the title for all my other view controllers inside viewWillAppear
so that the title is always updated just before the view appears (in case it is removed by tricks like this).
self.navigationController.navigationBar.topItem.title = @"";
Here's what I'm doing me, which is simpler to remove the title of back button
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar?.backItem?.title = ""
}
In the prepareForSegue: method of your first ViewController you set that views title to @"", so when the next view is pushed it will display the previous ViewController title which will be @"".
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
self.navigationItem.title = @" ";
}
The only problem with this is that when you hit the back button your previous view won't have a title, so you may add it again on viewWillAppear:
- (void)viewWillAppear:(BOOL)animated{
self.navigationItem.title = @"First View Title";
}
I don't like very much this solution but it works and i didn't find other way to do it.
I am listing out the solutions which worked for me so far.
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.topItem?.title = "" // 1
let barAppearace = UIBarButtonItem.appearance()
barAppearace.setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics:UIBarMetrics.Default) // 2
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Normal) //3
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Highlighted) //4
}
Just entering a single space for the Back button navigation item works!!
This is using subclass navigationController
removes the "Back".
I'm using this to remove it, permanently through the app.
//.h
@interface OPCustomNavigationController : UINavigationController
@end
//.m
@implementation OPCustomNavigationController
- (void)awakeFromNib
{
[self backButtonUIOverride:YES];
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self backButtonUIOverride:NO];
[super pushViewController:viewController animated:animated];
}
- (void)backButtonUIOverride:(BOOL)isRoot
{
if (!self.viewControllers.count)
return;
UIViewController *viewController;
if (isRoot)
{
viewController = self.viewControllers.firstObject;
}
else
{
int previousIndex = self.viewControllers.count - 1;
viewController = [self.viewControllers objectAtIndex:previousIndex];
}
viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@""
style:UIBarButtonItemStylePlain
target:nil
action:nil];
}
@end
Only need to set blank title text in ParentViewController.
self.navigationItem.title=@"";
If you need title text then Put below two methods in ParentViewController.
-(void)viewWillAppear:(BOOL)animated
{
self.navigationItem.title = @"TitleText";
}
-(void)viewWillDisappear:(BOOL)animated
{
self.navigationItem.title=@"";
}
This works for me to display just the 'back' chevron without any text:
self.navigationController.navigationBar.topItem.title = @"";
Set this property in viewDidLoad
of the View Controller presenting the navigation bar and it will do the trick.
Note: I have only tested it in iOS 7, which is within scope of the question.
You can also use this:
UIBarButtonItem *temporaryBarButtonItem = [[UIBarButtonItem alloc] init];
temporaryBarButtonItem.title = @"";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];
This works for me
Simple solution to this problem, working on iOS7 as well as 6, is to set custom title view in viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.text = self.title;
titleLabel.backgroundColor = [UIColor clearColor];
[titleLabel sizeToFit];
self.navigationItem.titleView = titleLabel;
}
Then, in viewWillAppear: you can safely call
self.navigationController.navigationBar.topItem.title = @" ";
Because your title view is custom view, it won't get overwritten when moving back in the navigation stack.
If you are using Storyboards you can go to Attributes Inspector
of the ViewController's Navigation Item
(click on Navigation Bar
) and set the Back Button
property to " " (one space character). This will set the Back Button title to one space character, leaving the chevron visible. No need to mess with code.
Note that this will set Back Button
title for the Back Button that will segue to this View Controller from the one that was pushed on top of it, not for the Back Button
that will be displayed inside this Controller!
On iOS7, Apple introduced two new properties to UINavigationBar, 'backIndicatorTransitionMaskImage' and 'backIndicatorImage'.
By simply calling once:
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:@"your_image"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:@"your_image_mask"]];
It will render a custom image instead of the default chevron glyph, inheriting the keyWindow's tint color.
And for removing the title, I'll suggest Kamaros's answer. Remember to call this code on the view controller that's pushing your new view controller. Removing the title text of an iOS UIBarButtonItem
Non of the answers helped me. But a trick did - I just cleared the title of the view controller that pushed (where the back button is going to) just before pushing it.
So when the previous view doesn't have a title, on iOS 7 the back button will only have an arrow, without text.
On viewWillAppear
of the pushing view, I placed back the original title.
I didn't have a lot of success with the provided answers but I did find a really simple work around. In your storyboard, you can click on your UIViewController's Navigation Item and set the back button text. I set it to a single ' ' space and it gave me the behavior I was looking for.
I couldn't get it to work using Guto Araujo's answer of navigationBar.topItem.title = @"";
However, I was able to get the desired effect by setting self.title = @""
in the init
method of my view controller. (Setting it in init
is important, viewDidLoad
won't work.)
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor clearColor],UITextAttributeTextColor,
nil];
[[UIBarButtonItem appearance] setTitleTextAttributes:attributes
forState:UIControlStateNormal];
I was having a same problem and I did it this way.
--EDIT--
this is a solution when you really want to remove title text of all UIBarbuttonItem. If you only want to remove the title of the back bar button item, there is no one simple convenient solution. In my case, since I only have few UIBarButtonItems that need to show title text I just changed those specific buttons' titleTextAttributes. If you want to be more specific use the code below, which will only change navigation bar buttons:
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor clearColor],UITextAttributeTextColor,
nil];
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setTitleTextAttributes:attributes
forState:UIControlStateNormal];
Just set offset for UIBarButtonItem appearance.
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000, -1000)
forBarMetrics:UIBarMetricsDefault];
SWIFT 3
navigationController?.navigationBar.topItem?.title = ""
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init];
barButton.title = @""; // blank or any other title
self.navigationController.navigationBar.topItem.backBarButtonItem = barButton;
This worked for me in iOS10. Call this from viewDidLoad of the view controller.
self.navigationController?.navigationBar.topItem?.title = ""
This worked for me in iOS 7+:
In viewDidLoad:
self.navigationItem.backBarButtonItem.title = @" ";
Yes, that's a space between the quotes.
I've made a very simple zero config category to hide all back button titles through out app you can check it out here. This question already has accepted answer, but for others it can be helpful.
EDIT:
.h file
#import <UIKit/UIKit.h>
@interface UINavigationController (HideBackTitle)
extern void PJSwizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector);
@end
.m file
#import "UINavigationController+HideBackTitle.h"
#import <objc/runtime.h>
@implementation UINavigationController (HideBackTitle)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
PJSwizzleMethod([self class],
@selector(pushViewController:animated:),
@selector(pj_pushViewController:animated:));
});
}
- (void)pj_pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
UIViewController *disappearingViewController = self.viewControllers.lastObject;
if (disappearingViewController) {
disappearingViewController.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}
if (!disappearingViewController) {
return [self pj_pushViewController:viewController animated:animated];
}
return [self pj_pushViewController:viewController animated:animated];
}
@end
void PJSwizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector)
{
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
BOOL didAddMethod =
class_addMethod(cls,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(cls,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
When you're setting the button's title, use @" " instead of @"".
--EDIT--
Does anything change when you try other strings? I'm using the following code myself successfully:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:backString style:UIBarButtonItemStyleDone target:nil action:nil];
[[self navigationItem] setBackBarButtonItem:backButton];
backString is a variable that is set to @" " or @"Back", depending on if I'm on iOS 7 or a lower version.
One thing to note is that this code isn't in the controller for the page I want to customize the back button for. It's actually in the controller before it on the navigation stack.
Implement your own UIViewController
base class and override setTitle:
.
@interface CustomViewController : UIViewController
@end
@implementation CustomViewController
- (void)setTitle:(NSString *)title {
super.title = @""; // This will remove the "Back" title
UILabel *titleView = [UILabel new];
// customize the label as you wish
titleView.text = title;
[titleView sizeToFit];
self.navigationItem.titleView = titleView;
}
@end
Now in any UIViewController
where you want to set the title, you can just write self.title = @"MyTitle"
as you normally would, and no text will appear on the back bar item when pushing a new UIViewController
.
In iOS 11 you can use the next code to hide back button title:
Swift:
UIBarButtonItem.appearance().setTitleTextAttributes([ NSForegroundColorAttributeName : UIColor.clear ], for: .normal)
UIBarButtonItem.appearance().setTitleTextAttributes([ NSForegroundColorAttributeName : UIColor.clear ], for: .highlighted)
This code doesn't remove title from navigation bar, but just makes it transparent, to back button still holds space for title. If you need to have more space for view controller title, then you need to use another solution.
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefaultPrompt];
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(10.0, NSIntegerMin) forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor],
NSFontAttributeName:[UIFont systemFontOfSize:1]}
forState:UIControlStateNormal];
I was able to cobble something together using DonnaLea's answer. This is how the solution appears in my UIViewController subclass:
var backItemTitle:String?
override func viewDidLoad() {
super.viewDidLoad()
//store the original title
backItemTitle = self.navigationController?.navigationBar.topItem?.title
//remove the title for the back button
navigationController?.navigationBar.topItem?.title = ""
}
override func willMoveToParentViewController(parent: UIViewController?) {
super.willMoveToParentViewController(parent)
if parent == nil {
//restore the orignal title
navigationController?.navigationBar.backItem?.title = backItemTitle
}
}
The problem with the original answer is that it removes the title from the controller when you pop back to it. Attempting to reset the title in viewWillDisappear is too late in the transition process; It causes the title to snap back in instead of animating nicely. However the willMoveToParentViewController happens sooner and allows for the correct behavior.
Caveat: I've only tested this with a normal UINavigationController push / pop. There might be additional unexpected behavior in other situations.
case : <Back as <
override func viewWillAppear(animated: Bool) {
navigationController!.navigationBar.topItem!.title = ""
}
To set the back button title for a view controller without changing its title use:
Objective-C:
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:self.navigationItem.backBarButtonItem.style target:nil action:nil];
Swift:
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
To be clear, this is done on the view controller that you would see if you hit the back button. i.e. instead of seeing '< Settings' you want to just see '<' then on your SettingsViewController you would put this in your init
. Then you don't get any of the problems of the title not showing when you're looking at the view controller itself.
If like me you're using a custom view instead of the UINavigationBar
and you're stuck with the back button then you have to do a bit of work that feels a bit cludgey.
[self.navigationController.navigationBar setHidden:NO];
self.navigationController.navigationBar.topItem.title = @"";
[self.navigationController.navigationBar setHidden:YES];
It seems like if it doesn't get presented then no matter what it'll try show a title, this means it's shown then hidden before it's drawn and solves the problem.
Perfect solution globally
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Normal)
UIBarButtonItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName:UIColor.clearColor()], forState: UIControlState.Highlighted)
return true
}
This is better solution.
Other solution is dangerous because it's hack.
extension UINavigationController {
func pushViewControllerWithoutBackButtonTitle(_ viewController: UIViewController, animated: Bool = true) {
viewControllers.last?.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
pushViewController(viewController, animated: animated)
}
}
Actually you can do this with just one trick:
Override UINavigationBar
class and add this line of code:
- (void)layoutSubviews{
self.backItem.title = @"";
[super layoutSubviews];
}
Then initialize your UINavigationController
with this custom UINavigationBar class.. etc. UINavigationController * navController = [[UINavigationController alloc] initWithNavigationBarClass:[CBCNavigationBar class] toolbarClass:nil];
Hope this helps
Sometimes it is helpful to see things in context. Here is a minimal project that hides the "back" text but still shows the arrow.
Storyboard
There is a show segue from the "Show Second View Controller" button to the second view controller.
I also added a Navigation Item to the second view controller so that it would have a title. This is optional. It does not affect the back button.
Code
FirstViewController.swift
import UIKit
class FirstViewController: UIViewController {
@IBAction func showSecondViewControllerButtonTapped(sender: UIButton) {
// hide the back button text
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
// Nothing at all needed here
}
On the storyboard select the navigation item for the first view controller (not the second). Just enter a space for the Back Button text.
If you want to remove the back button item title in iOS11, you can try it!
@implementation UIView (PrivateBackButton)
+ (void)initialize {
if ([NSProcessInfo processInfo].operatingSystemVersion.majorVersion < 11.0) return;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[NSObject hookInstanceMethodForClass:[self class] originalMethod:@selector(layoutSubviews) newMethod:@selector(mc_layoutSubviews)];
});
}
- (void)mc_layoutSubviews {
[self mc_layoutSubviews];
[self updateiOS11LaterUI];
}
- (void)updateiOS11LaterUI {
if ([NSProcessInfo processInfo].operatingSystemVersion.majorVersion < 11.0) return;
if (![self isKindOfClass:NSClassFromString(@"_UIBackButtonContainerView")]) return;
[self removeAllSubviews];
[self.superview mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(@44);
}];
}
@end
Swift 3.1 You can do this by implementing the delegate method of UINavigationController. It'll hide the Title with back button only, we'll still get the back arrow image and default functionality.
func navigationController(_ navigationController: UINavigationController,
willShow viewController: UIViewController, animated: Bool) {
let item = UIBarButtonItem(title: " ", style: .plain, target: nil,
action: nil)
viewController.navigationItem.backBarButtonItem = item
}
extension UIViewController{
func hideBackButton(){
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
Source: Stackoverflow.com