Reputation: 1507
How can I hide the Back Button Text from an UINavigation Controller? I will only have the "<" and not "< Back"
Upvotes: 128
Views: 131068
Reputation: 737
if #available(iOS 13.0, *) {
let appearance = UINavigationBarAppearance()
appearance.backButtonAppearance.normal.titlePositionAdjustment = UIOffset.init(horizontal: -300.0, vertical: 0.0)
}else{
let barButtonApperance = UIBarButtonItem.appearance()
barButtonApperance.setTitleTextAttributes([NSAttributedString.Key.foregroundColor:AppColor.PrimaryGray.value], for: UIControl.State.normal)
}
Upvotes: 2
Reputation: 578
In iOS 15, I could only get the back button text to disappear using the bar appearance API. It seems like overkill, but I've ended up reusing this all over an app. Here's an extension with a bunch of other useful pieces to customize a nav bar. Setting backButtonTextColor
to .clear
does the trick for this particular issue.
extension UIViewController {
@objc func setNavBarAppearance(with backgroundColor: UIColor,
titleColor: UIColor? = nil,
shadowColor: UIColor? = nil,
tintColor: UIColor? = nil,
backButtonTextColor: UIColor? = nil) {
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = backgroundColor
if let titleColor = titleColor {
appearance.titleTextAttributes = [.foregroundColor: titleColor]
}
if let shadowColor = shadowColor {
appearance.shadowColor = shadowColor
}
if let tintColor = tintColor {
navigationController?.navigationBar.tintColor = tintColor
}
if let backButtonTextColor = backButtonTextColor {
let backButtonAppearance = UIBarButtonItemAppearance()
backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: backButtonTextColor]
appearance.backButtonAppearance = backButtonAppearance
}
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
}
}
Call it in your view controller's viewDidLoad
like:
setNavBarAppearance(with: .systemBackground, backButtonTextColor: .clear)
Upvotes: 0
Reputation: 8105
The problem with most solutions here is that setting an empty text on the back item does not work well with the new functionality for long press on back buttons. Instead of showing proper titles, it is just showing an empty list
Instead, you can use the new button display mode for iOS14 or rely on the new appearance APIs for iOS13 , to set the text to size 0. Note that some people are playing with the color (clear), that doesnt work well either because it uses the space and removes it from your titles. If the title is long enough, you will see it clipped
Resulting code:
public extension UINavigationBar {
func fixAppearance() {
if #available(iOS 14.0, *) {
topItem?.backButtonDisplayMode = .minimal
} else if #available(iOS 13.0, *) {
let newAppearance = standardAppearance.copy()
newAppearance.backButtonAppearance.normal.titleTextAttributes = [
.foregroundColor: UIColor.clear,
.font: UIFont.systemFont(ofSize: 0)
]
standardAppearance = newAppearance
} else {
topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
}
}
Then you just need to call that method when view controllers are presented, so either you call it from a base class (on viewWillAppear
for example) or you add some delegate to the navigation controller like in other answers of this post.
Upvotes: 6
Reputation: 149
Swift 5
viewController.navigationItem.backButtonDisplayMode = .minimal
Upvotes: 7
Reputation: 2147
UINavigationControllerDelegate's navigationController(_, willShow:, animated:)
method implementation did the trick for me.
Here goes the full view controller source code. if you want to apply this throughout the app, make all viewcontrollers to derive from BaseViewController
.
class BaseViewController: UIViewController {
// Controller Actions
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateNavigationBar()
}
//This is for custom back button image.
func updateNavigationBar() {
let imgBack = UIImage(named: "icon_back")
self.navigationController?.navigationBar.backIndicatorImage = imgBack
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = imgBack
self.navigationItem.backBarButtonItem = UIBarButtonItem()
}
}
extension BaseViewController: UINavigationControllerDelegate {
//This is to remove the "Back" text from back button.
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.backBarButtonItem = UIBarButtonItem()
}
}
Upvotes: 0
Reputation: 55
XCode 11.5 Swift 5
A very simple - though perhaps a little hacky - way of doing programmatically this if you don't need the custom back button is to set the font size equal to zero in the view controller you're pushing onto the stack, calling something like this from viewDidLoad
private func setupNavBar() {
let appearance = UINavigationBarAppearance()
appearance.configureWithDefaultBackground()
let backButtonAppearance = UIBarButtonItemAppearance()
backButtonAppearance.normal.titleTextAttributes = [.font: UIFont(name: "Arial", size: 0)!]
appearance.backButtonAppearance = backButtonAppearance
navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
navigationItem.compactAppearance = appearance
}
Upvotes: 0
Reputation: 5647
If you're targeting iOS 13 and later you can use this new API to hide the back button title globally.
let backButtonAppearance = UIBarButtonItemAppearance()
backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
UINavigationBar.appearance().standardAppearance.backButtonAppearance = backButtonAppearance
UINavigationBar.appearance().compactAppearance.backButtonAppearance = backButtonAppearance
UINavigationBar.appearance().scrollEdgeAppearance.backButtonAppearance = backButtonAppearance
Upvotes: 4
Reputation: 4765
I tried some above and below but they didn't work. This worked for me:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.topItem?.title = ""
}
Upvotes: 25
Reputation: 739
My solution: - XCode: 10.2.1 - Swift: 5
Upvotes: 0
Reputation: 474
The back text come from last View Controller's navigationItem.title
,and navigationItem.title
is automaticly set by self.title
. So easy way to solve the problem is hook setTitle:
,make sure navigationItem.title = @""
Put this code at AppDelegate.m
will make it ok。
[UIViewController aspect_hookSelector:@selector(setTitle:)
withOptions:AspectPositionAfter
usingBlock:^(id<AspectInfo> aspectInfo, NSString *title) {
UIViewController *vc = aspectInfo.instance;
vc.navigationItem.titleView = ({
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
titleLabel.text = title;
titleLabel;
});
vc.navigationItem.title = @"";
} error:NULL];
More details at https://www.jianshu.com/p/071bc50f1475 (Simple Chinease)
Upvotes: 0
Reputation: 1460
You can implement UINavigationControllerDelegate
like this:
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
let item = UIBarButtonItem(title: " ", style: .Plain, target: nil, action: nil)
viewController.navigationItem.backBarButtonItem = item
}
class MyNavigationController: UINavigationController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let item = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
viewController.navigationItem.backBarButtonItem = item
}
}
backBarButtonItem
is nil
by default and it affects next pushed controller, so you just set it for all controllers
Upvotes: 94
Reputation: 1219
Setting title of the back button to @""
or nil
won't work. You need to set the entire button empty (without a title or image):
[self.navigationItem setBackBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]];
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
This should be done on the view controller that's on top of your view controller in navigation stack (i.e. from where you navigate to your VC via pushViewController
method)
Upvotes: 56
Reputation: 2595
A lot of answers already, here's my two cents on the subject. I found this approach really robust. You just need to put this in viewController before segue.
Swift 4:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Upvotes: 5
Reputation: 492
-(void)setNavigationItems{
UIBarButtonItem *leftBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"**Your title here**" style:UIBarButtonItemStyleBordered target:self action:@selector(backButtonClicked)];
self.navigationController.navigationBar.topItem.backBarButtonItem=leftBarButtonItem;
}
-(void)backButtonClicked{
[self.navigationController popViewControllerAnimated:YES];
}
Upvotes: 0
Reputation: 11
I was struggling with this because I had a custom navigation controller.
I was able to remove the back item text in all view controllers with this code in my custom navigation controller class
override func viewDidLayoutSubviews() {
self.navigationBar.backItem?.title = ""
}
This removes all of the back item titles using this custom navigation controller.
Upvotes: 1
Reputation: 2382
The following method works on iOS 11 and is safe to not crash on other iOS versions. Doing this may get your app rejected in App Store review since both UIModernBarButton and UIBackButtonContainerView are private APIs. Place in AppDelegate.
if
let UIModernBarButton = NSClassFromString("_UIModernBarButton") as? UIButton.Type,
let UIBackButtonContainerView = NSClassFromString("_UIBackButtonContainerView") as? UIView.Type {
let backButton = UIModernBarButton.appearance(whenContainedInInstancesOf: [UIBackButtonContainerView.self])
backButton.setTitleColor(.clear, for: .normal)
}
Upvotes: -2
Reputation: 9148
For those who want to hide back button title globally.
You can swizzle viewDidLoad
of UIViewController
like this.
+ (void)overrideBackButtonTitle {
NSError *error;
// I use `Aspects` for easier swizzling.
[UIViewController aspect_hookSelector:@selector(viewDidLoad)
withOptions:AspectPositionBefore
usingBlock:^(id<AspectInfo> aspectInfo)
{
UIViewController *vc = (UIViewController *)aspectInfo.instance;
// Check whether this class is my app's view controller or not.
// We don't want to override this for Apple's view controllers,
// or view controllers from external framework.
NSString *className = NSStringFromClass([vc class]);
Class class = [NSBundle.mainBundle classNamed:className];
if (!class) {
return;
}
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@" " style:UIBarButtonItemStylePlain target:nil action:nil];
vc.navigationItem.backBarButtonItem = backButton;
} error:&error];
if (error) {
NSLog(@"%s error: %@", __FUNCTION__, error.localizedDescription);
}
}
Usage:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[self class] overrideBackButtonTitle];
return YES;
}
Upvotes: 2
Reputation: 1942
Finally found perfect solution to hide default back text in whole app.
Just add one transparent Image and add following code in your AppDelegate.
UIBarButtonItem.appearance().setBackButtonBackgroundImage(#imageLiteral(resourceName: "transparent"), for: .normal, barMetrics: .default)
Upvotes: -1
Reputation: 333
Swift 3.1 You can do this by implementing the delegate method of UINavigationController.
func navigationController(_ navigationController: UINavigationController,
willShow viewController: UIViewController, animated: Bool) {
/** It'll hide the Title with back button only,
** we'll still get the back arrow image and default functionality.
*/
let item = UIBarButtonItem(title: " ", style: .plain, target: nil,
action: nil)
viewController.navigationItem.backBarButtonItem = item
}
Upvotes: 3
Reputation: 1313
Alternative way - use custom NavigationBar class.
class NavigationBar: UINavigationBar {
var hideBackItem = true
private let emptyTitle = ""
override func layoutSubviews() {
if let `topItem` = topItem,
topItem.backBarButtonItem?.title != emptyTitle,
hideBackItem {
topItem.backBarButtonItem = UIBarButtonItem(title: emptyTitle, style: .plain, target: nil, action: nil)
}
super.layoutSubviews()
}
}
That is, this remove back titles whole project. Just set custom class for UINavigationController.
Upvotes: 5
Reputation: 339
This is my resolution for iOS11, I change the appearance of UIBarButtonItem in applicationDidFinishLaunchingWithOptions :
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-100, 0), for:UIBarMetrics.default)
You can't change Y offset, because it will change the back bar button's position too in iOS11, but it's OK in iOS10 and below.
Upvotes: 3
Reputation: 48085
Use a custom NavigationController
that overrides pushViewController
class NavigationController: UINavigationController {
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
viewController.navigationItem.backBarButtonItem =
UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
super.pushViewController(viewController, animated: animated)
}
}
Upvotes: 4
Reputation: 625
In iOS 11, we found that setting UIBarButtonItem
appearance's text font/color to a very small value or clear color will result other bar item to disappear (system does not honor the class of UIBarButton item anymore, it will convert it to a _UIModernBarButton
). Also setting the offset of back text to offscreen will result flash during interactive pop.
So we swizzled addSubView
:
+ (void)load {
if (@available(iOS 11, *)) {
[NSClassFromString(@"_UIBackButtonContainerView") jr_swizzleMethod:@selector(addSubview:) withMethod:@selector(MyiOS11BackButtonNoTextTrick_addSubview:) error:nil];
}
}
- (void)MyiOS11BackButtonNoTextTrick_addSubview:(UIView *)view {
view.alpha = 0;
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (id)view;
[button setTitle:@" " forState:UIControlStateNormal];
}
[self MyiOS11BackButtonNoTextTrick_addSubview:view];
}
Upvotes: 0
Reputation: 3749
I tried everything in this post. The only working solution is @VoidLess's
Here is the same answer but more complete
class CustomNavigationController: UINavigationController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.delegate = self
}
}
// MARK:UINavigationControllerDelegate
extension CustomNavigationController {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
}
}
Upvotes: 3
Reputation: 453
In Swift3,
If you set global setting
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// ..
let BarButtonItemAppearance = UIBarButtonItem.appearance()
BarButtonItemAppearance.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .normal)
BarButtonItemAppearance.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.clear], for: .highlighted)
// ...
}
Upvotes: 2
Reputation: 596
The only thing which works with no side-effects is to create a custom back button. As long as you don't provide a custom action, even the slide gesture works.
extension UIViewController {
func setupBackButton() {
let customBackButton = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
navigationItem.backBarButtonItem = customBackButton
}}
Unfortunately, if you want all back buttons in the not to have any titles, you need to setup this custom back button in all your view controllers :/
override func viewDidLoad() {
super.viewDidLoad()
setupBackButton()
}
It is very important you set a whitespace as the title and not the empty string.
Upvotes: 14
Reputation: 3086
Set Title of the Previous VC to " " string with space. and title with the back button will be replaced with single space string.
Self.title = " "
On Back press again reset the title to original one in the viewWillAppear.
Upvotes: 4
Reputation: 8576
In the interface builder, you can select the navigation item of the previous controller and change the Back Button
string to what you'd like the back button to appear as. If you want it blank, for example, just put a space.
You can also change it with this line of code:
[self.navigationItem.backBarButtonItem setTitle:@"Title here"];
Or in Swift:
self.navigationItem.backBarButtonItem?.title = ""
Upvotes: 124
Reputation: 107
to remove the Text from backbutton programmatically, used below Code this will work form xcode7 and above.
self.navigationController.navigationBar.topItem.title = @" ";
or
manualLy in storyboards, select the navigation bar on the view controller and put " " in back button text.
this will work. thanks
Upvotes: 9
Reputation: 44
This is from my xamarin.forms code, the class derives from NavigationRenderer
NavigationBar.Items.FirstOrDefault().BackBarButtonItem = new UIBarButtonItem( "", UIBarButtonItemStyle.Plain, null);
Upvotes: -5