Как мне изменить название кнопки “Назад” на панели навигации

StackOverflow https://stackoverflow.com/questions/1449339

Вопрос

В настоящее время значением по умолчанию для кнопки левой панели является заголовок представления, которое загрузило текущее, другими словами, представление, которое будет отображаться при нажатии кнопки (кнопка назад).

Я хочу изменить текст, отображаемый на кнопке, на что-то другое.

Я попытался поместить следующую строку кода в метод viewDidLoad контроллера представления, но, похоже, это не работает.

self.navigationItem.leftBarButtonItem.title = @"Log Out";

Что мне следует делать?

Спасибо.

Это было полезно?

Решение

Это должно быть помещено в метод, который вызывает ViewController под названием "newTitle".Непосредственно перед операцией push или popViewController.

UIBarButtonItem *newBackButton = 
        [[UIBarButtonItem alloc] initWithTitle:@"NewTitle" 
                                         style:UIBarButtonItemStyleBordered 
                                        target:nil 
                                        action:nil];
[[self navigationItem] setBackBarButtonItem:newBackButton];
[newBackButton release];

Другие советы

В childVC это сработало для меня...

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

Работает и в Swift!

self.navigationController!.navigationBar.topItem!.title = "Back"

Вот документация для backBarButtonItem Элемент обратной связи:

"Когда этот элемент навигации находится непосредственно под верхним элементом в стеке , навигационный контроллер получает кнопку "Назад" для панели навигации из этого элемента навигации.[...] Если вы хотите указать пользовательское изображение или заголовок для кнопки "Назад", вы можете назначить пользовательский элемент кнопки панели (с вашим пользовательским названием или изображением) этому вместо этого свойству ".

Контроллер просмотра A (тот "родитель" контроллер просмотра):

self.title = @"Really Long Title";
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Short" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;

Когда любой другой контроллер просмотра B находится поверх навигационного стека, и A находится прямо под ним, Bкнопка " Назад " будет иметь заголовок "Короткий".

в Xcode 4.5 с использованием раскадровки, безусловно, самое простое решение, которое я нашел, когда значение кнопки "Назад" не должно изменяться динамически, - это использовать поле "Кнопка назад", связанное с элементом навигации контроллера представления, к которому вы хотите, чтобы кнопка "Назад" указывала что-то еще.

например ,на скриншоте ниже я хочу, чтобы кнопка "Назад" для контроллеров просмотра, которую я нажимаю, имела "Назад" в качестве названия кнопки "Назад".

enter image description here

конечно, это не сработает, если вам нужно, чтобы кнопка "Назад" каждый раз говорила что-то немного другое ... для этого здесь есть все другие решения.

Я знаю, вопрос очень старый, но я нашел хорошее решение.

UIBarButtonItem *barButton = [[UIBarButtonItem alloc] init];
barButton.title = @"Custom Title";
self.navigationController.navigationBar.topItem.backBarButtonItem = barButton;

Работает из childView!Протестировано с iOS 7.

Возможно, я излишне упрощаю, но из документации Apple следует формулировка:

Если a обычай элемент кнопки панели не указан ни одним из контроллеров представления, a кнопка возврата по умолчанию используется, и его заголовку присваивается значение свойства title предыдущего контроллера представления, то есть контроллера представления на один уровень ниже в стеке.

Решение, отмеченное как правильное выше, устанавливает элемент кнопки по умолчанию из родительского контроллера.Это правильный ответ, но я решаю проблему, изменяя self.title свойство UIViewController непосредственно перед тем, как поместить новый контроллер в стек NavigationController.

Это автоматически обновит заголовок кнопки "Назад" на следующем контроллере, и до тех пор, пока вы устанавливаете self.title вернуться к тому, в чем это должно быть viewWillAppear Я не вижу, чтобы этот метод вызывал слишком много проблем.

Для меня это работает лучше.Попробуй :

 self.navigationController.navigationBar.topItem.backBarButtonItem = [[UIBarButtonItem alloc] 
initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];

В Swift / iOS8 у меня сработало следующее:

let backButton = UIBarButtonItem(
      title: "Back Button Text",
      style: UIBarButtonItemStyle.Bordered,
      target: nil,
      action: nil
);

self.navigationController.navigationBar.topItem.backBarButtonItem = backButton;

Перенесено из ответа Фелипе.

Хорошо, вот способ.Если у вас есть контроллер просмотра "first" и вы перемещаетесь по другому контроллеру просмотра "second" нажатием кнопки или т.д.тебе нужно проделать кое-какую работу.Сначала вам нужно создать BarButtonItem во "втором" методе viewDidLoad контроллера представления следующим образом;

    UIBarButtonItem *btnBack = [[UIBarButtonItem alloc]
                                   initWithTitle:@"Back" 
                                   style:UIBarButtonItemStyleBordered
                                   target:self
                                   action:@selector(OnClick_btnBack:)];
    self.navigationItem.leftBarButtonItem = btnBack;
    [btnBack release];

После того, как вы сделаете это, вам нужно написать код для действия "btnBack" в том же файле .m, например;

-(IBAction)OnClick_btnBack:(id)sender  {
      [self.navigationController popViewControllerAnimated:YES];
    //[self.navigationController pushViewController:self.navigationController.parentViewController animated:YES];
}

Вот и все.

У меня был родительский контроллер представления с очень длинным названием.Это привело к тому, что текст кнопки "Назад" перетек в заголовок дочернего контроллера представления.

Перепробовав кучу разных решений, вот что я в итоге сделал (развивая подход @john.k.doe):

Используя Xcode 7.2, Swift 2

  1. В раскадровке добавьте Navigation Item к тому Родитель Просмотр сцены контроллера (не дочернего VC)

navigation item

  1. На Attributes Inspector о вашем новом Navigation Item, введите в space персонаж в Back Button поле.Подробнее об этом позже.

navigation item in View Hierarchy

add a space character to the Back Button field

  1. В Родитель просмотр контроллера, добавьте следующий код:

фрагмент текста:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    switch segue.destinationViewController {
    case is ChildViewController:
        navigationItem.backBarButtonItem?.title = ""
    default:
        navigationItem.backBarButtonItem?.title = "Full Parent Title"
    }
}

Объяснение:

Кнопка "Назад" вроде как принадлежит родительскому контроллеру представления.В Navigation Item дает вам дескриптор кнопки "Назад", чтобы вы могли задать заголовок в коде или в раскадровке.

Примечание:

Если вы оставите Navigation Item Back Button введите текст в качестве пустой строки по умолчанию, заголовок кнопки "Назад" станет "Back".

Другие подходы работают, зачем использовать этот?:

Хотя заголовок кнопки "Назад" на дочернем контроллере просмотра можно переопределить, было непросто разобраться с ним, пока он не успел ненадолго высветиться на экране.

Некоторые из подходов создают новую кнопку "Назад" и переопределяют существующую.Я уверен, что это работает и, вероятно, необходимо в некоторых случаях использования.Но я предпочитаю использовать существующие API, когда это возможно.

Изменение title использование родительского контроллера представления является самым быстрым решением для некоторых ситуаций.Однако это изменяет родительский заголовок, поэтому вам придется управлять состоянием.Вещи также становятся беспорядочными с Tab Bar Controller поскольку изменения названия вызывают побочные эффекты при Tab Bar Item титулы.

Для тех, кто использует раскадровки, просто выберите родительский (не тот, который содержит целевой вид) фрейм контроллера представления (обязательно щелкните правой кнопкой мыши на панели навигации, затем откройте инспектор атрибутов, где вы найдете три формы ввода.Третья "кнопка назад" - это то, что мы ищем.

Быстрая версия:

В вашем дочернем ViewController:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.backItem?.title = "TEXT"
}

Вот еще один способ сделать это.

В вашем родительском контроллере представления реализуйте следующий метод:

- (void) setBackBarButtonItemTitle:(NSString *)newTitle {
  self.navigationItem.backBarButtonItem.title = newTitle;
}

В вашем дочернем контроллере просмотра, когда вы захотите изменить заголовок, это сработает:

NSArray *viewControllerArray = [self.navigationController viewControllers];
int parentViewControllerIndex = [viewControllerArray count] - 2;
[[viewControllerArray objectAtIndex:parentViewControllerIndex] setBackBarButtonItemTitle:@"New Title"];

Я так и не смог получить parentViewController свойство работать:

[(ParentViewController *)(self.navigationController.parentViewController) setBackBarButtonItemTitle:@"New Title"];

Я не знаю, является ли это ошибкой или я не использую ее должным образом.Но захват предпоследнего контроллера просмотра в viewControllers массив указывает на родительский контроллер представления, и я могу корректно вызывать родительские методы по этой ссылке.

ОК.Лично я ненавидел все эти варианты.Поэтому я придумал свой собственный.

Основываясь на информации, которую я видел.Похоже, что Предыдущий контроллер просмотра управляет своей собственной кнопкой "Назад", которая будет представлена на нажатом контроллере просмотра.

Я создал метод отложенной загрузки для navigationItem на контроллере, который хочет изменить кнопку "Назад".

Мой - это Контроллер Приглашенного покупателя

Пригласить покупателя - это текст, который задан по умолчанию.

но кнопка "Назад" должна была быть Приглашающей

Вот код, который я использовал для создания кнопки "Назад".

Я поместил этот код в начало файла реализации контроллера (.m), и он автоматически переопределил метод super.

- (UINavigationItem *)navigationItem{
    UINavigationItem *item = [super navigationItem];
    if (item != nil && item.backBarButtonItem == nil)
    {
        item.backBarButtonItem = [[[UIBarButtonItem alloc] init] autorelease];
        item.backBarButtonItem.title = @"Invite";
    }

    return item;
}

Я чувствую, что это гораздо более элегантный способ добиться этого.

Я помещаю этот код в одно место, и он автоматически заполняется при необходимости.

Нет необходимости вызывать код перед каждым push-запросом.

Надеюсь, это поможет

UIBarButtonItem *btnBack = [[UIBarButtonItem alloc]
                                   initWithTitle:@"Back" 
                                   style:UIBarButtonItemStyleBordered
                                   target:self
                                   action:@selector(OnClick_btnBack:)];
    self.navigationItem.leftBarButtonItem = btnBack;
    [btnBack release];

Вот вам и ответ:

В viewDidAppear:animated (НЕ в viewDidLoad) выполните следующие действия

- (void)viewDidAppear:(BOOL)animated
{
     [self.navigationController.navigationBar.backItem setTitle:@"anything"];

     // then call the super
     [super viewDidAppear:animated];
}

Это если вы хотите сохранить форму кнопки "Назад".

Ни одно из описанных здесь решений не сработало для меня.Итак, что я сделал, так это удалил название из сцены, откуда я пришел, следующим образом:

self.title = @"";

Таким образом, при представлении новой сцены обратный текст не появляется.

Я абсолютно согласен, что это вообще не совсем ясное решение, но сработало, и ни одно из объясненных решений не сработало для меня.

Для Swift:

    // Rename back button
    let backButton = UIBarButtonItem(
        title: "Back",
        style: UIBarButtonItemStyle.Plain, // Note: .Bordered is deprecated
        target: nil,
        action: nil
    )
    self.navigationController!.navigationBar.topItem!.backBarButtonItem = backButton

Я обнаружил, что самый простой способ изменить название кнопки "Назад" - это присвоить заголовку view controllers значение заголовка кнопки "Назад", а затем заменить titleView в элементе навигации view controllers на пользовательскую метку с ее реальным именем.

Вот так:

CustomViewController.m

@implementation CustomViewController

- (NSString*)title {
    return @"Back Button Title";
}

- (void)viewDidLoad {
    [super viewDidLoad];
    UILabel* customTitleView = [[UILabel alloc] initWithFrame:CGRectZero];
    customTitleView.text = @"Navigation Bar Title";
    customTitleView.font = [UIFont boldSystemFontOfSize:20];
    customTitleView.backgroundColor = [UIColor clearColor];
    customTitleView.textColor = [UIColor whiteColor];
    customTitleView.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
    customTitleView.shadowOffset = CGSizeMake(0, -1);

    [customTitleView sizeToFit];

    self.navigationItem.titleView = [customTitleView autorelease];
}

@end

Это заставит ваш заголовок в UINavigationBar выглядеть так, как если бы он был родным.Предоставление контроллеру просмотра возможности иметь отдельный заголовок и название кнопки "Назад".

В случае контроллеров просмотра A и B, A отвечает за указание того, как должна выглядеть кнопка возврата, в то время как B отображается.

Редактировать:При этом также сохраняется родной вид кнопки "Назад" (элемент кнопки на панели со стрелкой слева).

Этот код тоже работает.Поместите это на корневой контроллер навигационного контроллера:

self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

Я обнаружил, что лучше всего изменить заголовок текущего контроллера вида в стеке навигации на нужный текст кнопки "Назад", прежде чем переходить к следующему контроллеру вида.

Например

self.navigationItem.title = @"Desired back button text";
[self.navigationController pushViewController:QAVC animated:NO];

Затем в viewDidAppear верните заголовку желаемый заголовок для исходного VC.Вуаля!

Я новичок в iOS, но я приведу свой очень простой ответ о переопределении класса навигационного контроллера.У меня есть простое переопределение методов push и pop и сохранение заголовка предыдущего контроллера просмотра.Извините за вставку в блок js.Был немного смущен тем, как вставить это в обычный блок кода.

#import "MyCustomNavController.h"


@implementation MyCustomNavController {

    NSString *_savedTitle;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated withBackBtnTitle:(NSString *)title {
    _savedTitle = self.topViewController.title;

    self.topViewController.title = title;
    [super pushViewController:viewController animated:animated];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated {

    [self.viewControllers objectAtIndex:self.viewControllers.count - 2].title = _savedTitle;
    return [super popViewControllerAnimated:animated];
}

@end

self.navigationController.navigationBar.backItem.title = @"TEXT";

И в Swift:

self.navigationController?.navigationBar.backItem?.title = "TEXT"
self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] 
                                              initWithTitle:@"Log out" 
                                              style:UIBarButtonItemStyleDone 
                                              target:nil 
                                              action:nil] autorelease];

вы можете поместить его куда угодно в коде parrent controller, что позволяет вам иметь разные обратные кнопки для разных дочерних представлений.

Большинство решений убивает оригинальный стиль BackButton (кнопка со стрелкой слева), добавляя обычную кнопку с желаемым заголовком.
Итак, чтобы сохранить оригинальный стиль, есть 2 способа:
1 - й:Использовать недокументированный стиль кнопки (110 или что-то в этом роде), чего я предпочитаю не делать.Но если вы хотите, вы могли бы найти, как это сделать, здесь, в stackoverflow.
2 - й:Чтобы использовать идею Тренскова.Мне это понравилось, и я использую его немного измененным.
Вместо переопределения заголовка - (NSString *) я решил сохранить исходный заголовок следующим образом (что позволяет мне использовать заголовки nib, а также заданный заголовок в состоянии push, кстати).

- (void)viewDidLoad {
    [super viewDidLoad];
    static NSString * backButtonTitle=@"Back"; //or whatever u want

    if (![self.title isEqualToString:backButtonTitle]){

        UILabel* customTitleView = [[UILabel alloc] initWithFrame:CGRectZero];
        customTitleView.text = self.title; // original title
        customTitleView.font = [UIFont boldSystemFontOfSize:20];
        customTitleView.backgroundColor = [UIColor clearColor];
        customTitleView.textColor = [UIColor whiteColor];
        customTitleView.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
        customTitleView.shadowOffset = CGSizeMake(0, -1);

        [customTitleView sizeToFit];

        self.navigationItem.titleView = [customTitleView autorelease];
        self.title = backButtonTitle; 
    }
}

Это решение работает хорошо и выглядит нативным.Также, если использовать его в методе viewDidLoad, это предотвращает выполнение более 1 раза.
Также я пробовал решение Jessedc, но оно выглядит плохо.Это приводит к изменению видимой пользователю строки заголовка "на лету" с исходной на желаемую BackButton и обратно.

Это работает для меня как "упрощенная" версия предыдущих опубликованных ответов.

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] init];

backButton.title = @"Go Back";

self.navigationItem.backBarButtonItem = backButton;

Не забудьте поместить код внутрь родительского контроллера представления (напримерпредставление, в котором есть ваше табличное представление или UITableViewController), не дочерний или подробный вид (например,UIViewController).

Вы можете легко локализовать строку кнопки "Назад" следующим образом:

backButton.title = NSLocalizedString(@"Back Title", nil);

У нас есть два VC A и B.

Если вы хотите изменить заголовок в B, напишите этот код в A

- (IBAction)goToBViewController:(UIButton *)sender {

    BViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"VC"];
    UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Your title here"
                                                                  style:UIBarButtonItemStylePlain
                                                                 target:nil
                                                                 action:nil];
    [[self navigationItem] setBackBarButtonItem:newBackButton];
    [self.navigationController pushViewController:vc animated:NO];

}

Swift 4.1 Xcode 9.4

let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "VC"])
let newBackButton = UIBarButtonItem.init(title: "Your title here", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
navigationController?.navigationBar.topItem?.backBarButtonItem = newBackButton
navigationController?.pushViewController(secondViewController!, animated: true)

Ответ Стэна был самым лучшим.Но у этого также есть проблема, когда вы используете контроллер с панелью вкладок и меняете заголовок контроллера, вы также можете изменить заголовок панели вкладок.Таким образом, лучший ответ - изменить только view_controller.navigationItem.title и использовать view_controller.navigationItem.title в функции.Ответ здесь: (С помощью ARC и добавьте их в viewDidLoad viewDidLoad)

  static NSString * back_button_title=@"Back"; //or whatever u want
  if (![view_controller.navigationItem.title isEqualToString:back_button_title]){
    UILabel* custom_title_view = [[UILabel alloc] initWithFrame:CGRectZero];
    custom_title_view.text = view_controller.navigationItem.title; // original title
    custom_title_view.font = [UIFont boldSystemFontOfSize:20];
    custom_title_view.backgroundColor = [UIColor clearColor];
    custom_title_view.textColor = [UIColor whiteColor];
    custom_title_view.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
    custom_title_view.shadowOffset = CGSizeMake(0, -1);

    [custom_title_view sizeToFit];

    view_controller.navigationItem.titleView = custom_title_view;
    view_controller.navigationItem.title = back_button_title;
  }

В моем собственном использовании я делаю это функцией, подобной этой, просто у меня есть функция с одной строкой кода в viewDidLoad.

+ (void)makeSubViewHaveBackButton:(UIViewController*) view_controller{
  static NSString * back_button_title=@"Back"; //or whatever u want
  if (![view_controller.navigationItem.title isEqualToString:back_button_title]){
    UILabel* custom_title_view = [[UILabel alloc] initWithFrame:CGRectZero];
    custom_title_view.text = view_controller.navigationItem.title; // original title
    custom_title_view.font = [UIFont boldSystemFontOfSize:20];
    custom_title_view.backgroundColor = [UIColor clearColor];
    custom_title_view.textColor = [UIColor whiteColor];
    custom_title_view.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
    custom_title_view.shadowOffset = CGSizeMake(0, -1);

    [custom_title_view sizeToFit];

    view_controller.navigationItem.titleView = custom_title_view;
    view_controller.navigationItem.title = back_button_title;
  }
}

Если вы хотите не только изменить текст кнопки "Назад" на тот же текст и сохранить исходную форму стрелки влево, но и что-то делать, когда пользователь нажимает кнопку "Назад", я рекомендую вам ознакомиться с моим "Пользовательский навигационный контроллер".

ПРОБЛЕМА:Текст "Назад" на панели навигации заменить нельзя.

Причина:Метка "Назад" устанавливается на панели навигации после нажатия на вид, потому что атрибуту .title в контроллере родительского вида было присвоено значение nil (или не инициализировано).

ОДНО ИЗ РЕШЕНИЙ:Если вы установите self.title="Независимо от того ...", вы увидите, что вместо "Назад" появится "Независимо от того ..." после нажатия кнопки new view controller.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top