UINavigationController „przycisk wstecz”?

147

„Przycisk wstecz” a UINavigationControllerdomyślnie pokazuje tytuł ostatniego widoku w stosie. Czy zamiast tego można umieścić niestandardowy tekst na przycisku Wstecz?

Ali Shafai
źródło
1
Ta praca dla mnieself.navigationController.navigationBar.topItem.title = @"Custom text";
huync

Odpowiedzi:

342

Z tego linku :

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

Jak powiedział Tyler w komentarzach:

nie rób tego w widocznym kontrolerze widoku, ale w kontrolerze widoku, który zobaczysz po naciśnięciu przycisku Wstecz

wodza
źródło
4
Zalecana . releaseUIBarButtonItem
Mehrdad Afshari
217
Zauważ również, że musisz to zrobić w kontrolerze widoku o jeden poziom wyżej w stosie. Innymi słowy, nie rób tego w widocznym kontrolerze widoku, ale w kontrolerze widoku, który zobaczysz po naciśnięciu przycisku Wstecz.
Tyler
6
Tylko po to, aby wyjaśnić komentarz Tylera, ponieważ na początku tego nie zrozumiałem: ustawienie backBarButtonItem w nawigacji kontrolerów widoku to ustawienie przycisku, który będzie wyświetlany, aby powrócić do tego kontrolera widoku. Należy również zauważyć, że chociaż nie ma stylu przycisku dla przycisku strzałki, ten przycisk i tak otrzyma styl strzałki. Użyłem UIBarButtonItemStylePlain i nadal mam styl przycisku strzałki.
Jon Steinmetz,
3
Sugestia: Zamiast zakładać styl, przekaż aktualnie ustawiony styl. W kodzie tej odpowiedzi zamień UIBarButtonItemStyleBorderedna wywołanie właściwości self.navigationItem.backBarButtonItem.style. Dokumentacja: developer.apple.com/library/ios/documentation/uikit/reference/…
Basil Bourque
1
Zauważ, że w ARC musisz pominąć wywołanie autorelease. więc masz self.navigationItem.backBarButtonItem = [[UIBarButtonItemocation] initWithTitle: @ "Tytuł niestandardowy" style: UIBarButtonItemStyleBordered target: zero akcja: nil];
bkbeachlabs
43

Możesz ustawić tekst w Interface Builder:

Wybierz element nawigacyjny kontrolera ViewController, do którego powróci przycisk Wstecz:

wprowadź opis obrazu tutaj

W inspektorze atrybutów panelu narzędzi wprowadź etykietę dla przycisku Wstecz:

wprowadź opis obrazu tutaj

Wolałbym takie podejście niż umieszczanie tytułu w kodzie, jak w zaakceptowanej odpowiedzi.

Zauważ również, że musisz to zrobić w kontrolerze widoku o jeden poziom wyżej w stosie. Innymi słowy, nie rób tego w widocznym kontrolerze widoku, ale w kontrolerze widoku, który zobaczysz po naciśnięciu przycisku Wstecz.
- Tyler

Petr Peller
źródło
To najlepsza odpowiedź, jaką do tej pory znalazłem.
Ayan Sengupta
2
Aby było jasne, należy to ustawić w elemencie nawigacyjnym kontrolera widoku, a nie w samym inspektorze atrybutów kontrolera widoku.
Patrick Przeczytaj
To najlepsza odpowiedź, jaką znalazłem.
bicepjai
To najlepsza odpowiedź
Alex Brown
2
Począwszy od Xcode 6.1.1 i działającego w systemie iOS 7, wydaje się, że oryginalny tytuł poprzedniego widoku NADAL zastąpi dowolny tytuł przycisku Wstecz, który tutaj ustawisz. Jeśli tytuł poprzedniego widoku zawiera więcej niż limit 11 znaków, przycisk Wstecz w następnym widoku powie po prostu „Wstecz”. Nie da się tego obejść poza utworzeniem nowego elementu paska nawigacji od podstaw, jak pokazano w odpowiedzi, która została najwyżej oceniona tutaj.
ray
22

Używam tego:

// In the current view controller, not the one that is one level up in the stack
- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.navigationBar.backItem.title = @"Custom text";
}
Trang
źródło
To prawie działa dla mnie, ale kiedy klikam przycisk Wstecz, tekst zmienia się z powrotem na tytuł rodzica na czas trwania animacji :-(
Danny Tuppeny
3
Spowoduje to zmianę tytułu przycisku Wstecz kontrolera w stosie. Nie zmienia to tytułu przycisku Wstecz aktualnie wyświetlanego kontrolera. Co gorsza: zmienia tytuł kontrolera wcześniejszy niż poprzedni!
lewiatan,
Jak zauważyli inni komentatorzy, ta metoda jest trochę nie do utrzymania. Nie polecałbym tego robić, ponieważ interfejs API nie zamierza tego używać. W przyszłości możesz być narażony na trudne błędy!
RickDT
11

Znalazłem poręczne rozwiązanie tego problemu, ustawiając po prostu tytuł kontrolera przed umieszczeniem innego kontrolera na stosie, na przykład:

self.navigationItem.title = @"Replacement Title";
[self.navigationController pushViewController:newCtrl animated:YES];

Następnie ustaw oryginalny tytuł w viewWillAppear, na przykład:

-(void)viewWillAppear:(BOOL)animated
{
  ...
  self.navigationItem.title = @"Original Title";
  ...
}

Działa to, ponieważ domyślnym zachowaniem UINavigationControllerpodczas tworzenia przycisku Wstecz podczas operacji wypychania jest użycie tytułu z poprzedniego kontrolera.

Aubrey Goodman
źródło
1
Problem z tym polega na tym, że tytuł zmienia się w starym widoku, ponieważ animuje się i wygląda nieco głupio. Żadne z podanych tutaj rozwiązań nie działa tak, jak chcesz :-(
Danny Tuppeny
1
Jest to idealne rozwiązanie w mojej sytuacji, ponieważ nie pokazuję paska nawigacyjnego na poprzednim ekranie, a chcę po prostu usunąć titleLabel z przycisku Wstecz na nowym ekranie i mam tylko strzałkę w kształcie litery V iOS7. Dlatego mogę po prostu ustawić pusty literał NSString dla tytułu.
siburb
naciśnięcie kontrolera widoku powoduje podniesienie wyjątku po dotknięciu pleców
Sumit
7

Tytuł przycisku wstecz jest domyślnie tytułem poprzedniego widoku, więc szybką sztuczką, której używam, jest umieszczenie następującego kodu w pliku .m poprzedniego widoku.

-(void)viewWillAppear:(BOOL)animated {

    // Set title
    self.navigationItem.title=@"Original Title";
}

-(void)viewWillDisappear:(BOOL)animated {

    // Set title
    self.navigationItem.title=@"Back";
}
AddisDev
źródło
Działa to całkiem nieźle w wielu przypadkach i jest całkiem proste ... tylko obserwacja jest taka, że ​​zastąpienie którejkolwiek z tych metod wymaga wywołania implementacji super w pewnym momencie nowej metody.
izk
2
W przypadku tej metody można zauważyć, że tytuł widoku nadrzędnego został zmieniony na „Wstecz” przed rozpoczęciem animacji wypychania. (I jakoś do bani, że jeśli przenieść to do sposobu viewDidDisappear, zobaczysz przełącznik dzieje po naciśnięciu ..)
James Boutcher
Uwielbiam tę metodę, ale problem z nią związany polega na tym, że „Oryginalny tytuł” ​​jest ustawiany prawidłowo, ale zawiera wielokropek, jeśli jest dłuższy niż „Wstecz”, co musi być spowodowane tym, że widok nie znajduje się jeszcze w hierarchii widoków , nie przekazuje widoku tytułu. Problem opisany powyżej przez @JamesBoutcher jest dla mnie niezauważalny ze względu na dużą prędkość początkową animacji. W rzeczywistości właśnie zdałem sobie sprawę, że problem, z którym się spotykam, jest szczególnie zauważalny z powodu wolno kończącej się animacji, w której ten problem jest wyraźny.
trss
Chociaż odpowiedź na stackoverflow.com/questions/1441699/ ... wydaje się być bardziej dostosowana niż to konieczne, jest to udokumentowana droga i co ważniejsze wydaje się być bardziej dostosowana do naszych intencji.
trss
6

w swojej metodzie init dodaj następujący kod:

- (id)initWithStyle:(UITableViewStyle)style {
    if(self = [super init]) {

        //...

        UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" 
                                             style:UIBarButtonItemStylePlain 
                                            target:self 
                                            action:@selector(goBack)];
        self.navigationItem.leftBarButtonItem = customBackButton;
        [customBackButton release];

        //...
    }
    return self;
}

następnie dodaj prostą metodę, aby umożliwić odrzucenie kontrolera widoku:

-(void)goBack {
    [self.navigationController popViewControllerAnimated:YES];  
}
valvoline
źródło
3

Dodaj następujący kod w viewDidLoad lub loadView

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

Przetestowałem to na iPhonie i iPadzie z iOS 9

samotni
źródło
Powinien to być self.navigationController? .NavigationBar.backItem? .Title = "Custom Text"
Peacemoon
1
jedyną różnicą, której potrzebowałem, było opcjonalne łańcuchowanie na właściwościach navigationControlleri topItem, np .:self.navigationController?.navigationBar.topItem?.title = "Custom Text"
Bulwinkel
2

Dodając do odpowiedzi wodzy. Uwaga z dokumentacji firmy Apple, że deklaracja backBarButtonItem jest taka:

@property(nonatomic, retain) UIBarButtonItem *backBarButtonItem

Dlatego odpowiedź Reina spowoduje wyciek pamięci, ponieważ zsyntetyzowany ustawiacz przekaże retaininstancję, która ją przekaże, która nigdy nie jest jawnie udostępniana. Możesz temu zaradzić, używającautorelease

 self.navigationItem.backBarButtonItem = 
      [[[UIBarButtonItem alloc] initWithTitle:@"Custom Title" 
         style:UIBarButtonItemStyleBordered
         target:nil
         action:nil] autorelease];  //<-- autoreleased

Możesz też wskazać zmienną na instancję, aby móc ją jawnie zwolnić później:

UIBarButtonItem* item = ...
self.navigationItem.backBarButtonItem = item;
[item release];

Mam nadzieję że to pomoże!

Eric Goldberg
źródło
Zauważ, że w dzisiejszych czasach, dzięki ARC, nie musisz się martwić o automatyczne wydanie (i rzeczywiście kompilator wyświetli błąd, jeśli spróbujesz automatycznie wydać w projekcie obsługującym ARC)
Eric Goldberg
2
- (void)viewDidLoad {
  [super viewDidLoad];

  UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
  self.navigationItem.backBarButtonItem = backButton;
  [backButton release];
}
LCANT
źródło
2

Odkryłem coś interesującego. Jeśli podklasujesz UINavigationControlleri nadpisujesz pushViewController:animated:metodę i robisz coś takiego: (pamiętaj, że używam ARC)

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] 
 initWithTitle: @"Back" 
 style: UIBarButtonItemStyleBordered
 target: nil action: nil];

viewController.navigationItem.backBarButtonItem = backButton;

[super pushViewController:viewController animated:animated];

Następnie dla wszystkich, ViewControllersktóre są naciskane za pomocą kontrolera nawigacyjnego, przycisk „Wstecz” będzie w nich automatycznie. Jeśli chcesz zmienić tekst dla niektórych kontrolerów widoku, możesz spróbować rzutować kontroler widoku na określoną klasę lub swój własny niestandardowy protokół (z którego dziedziczy kontroler widoku, który może mieć metodę taką jakbackButtonText lub coś podobnego), co może dać ci pewne informacje o kontrolerze widoku, które się pojawiają, aby można było dostosować do niego tekst przycisku Wstecz. Teraz tekst przycisku Wstecz jest obsługiwany w miejscu, za które ponosi wyłączną odpowiedzialność. Muszę przyznać, że tworzenie nowego przycisku do zmiany tekstu jest do bani, ale cóż.

Czy ktoś może wymyślić powód, dla którego nie miałby tego robić w ten sposób? Przynajmniej nie musisz majstrować przy tytułach kontrolera widoku ani pamiętać o utworzeniu nowego przycisku Wstecz przed naciśnięciem kontrolera widoku na kontrolerze nawigacyjnym.

Dandré
źródło
0

odpowiedź wodzy działa dobrze.

Zwróć uwagę, że jeśli naciśniesz więcej niż jeden kontroler widoku, zmieniony tytuł przycisku wstecz pojawi się dla każdego z nich, co może nie być tym, czego chcesz.

W takim przypadku musisz utworzyć niestandardowy UIBarButtonItem za każdym razem, gdy wypychasz kontroler widoku.

Upewnij się również, że zrobiłeś to przed naciśnięciem kontrolera widoku, w przeciwnym razie pojawi się czkawka na ekranie, gdy zmieni się tytuł.

Northernman
źródło
0

Rozwijając sugestię Aubrey, możesz to zrobić w kontrolerze widoku dziecka:

utwórz dwie zmienne do przechowywania starych wartości navigationItem.title elementu nadrzędnego i navigationItem elementu nadrzędnego

UINavigationItem* oldItem;
NSString* oldTitle;

w viewDidLoad, dodaj następujące informacje:

oldItem = self.navigationController.navigationBar.topItem;  
oldTitle = oldItem.title;  
[oldItem setTitle: @"Back"];  

w viewWillDisappear, dodaj następujące informacje:

[oldItem setTitle: oldTitle];  
oldTitle = nil;  // do this if you have retained oldTitle
oldItem = nil;   // do this if you have retained oldItem

To nie jest idealne. Zobaczysz, że tytuł widoku nadrzędnego zmienia się w miarę animacji nowego kontrolera. ALE pozwala to na niestandardowe oznaczenie przycisku Wstecz i utrzymanie go w kształcie standardowego przycisku Wstecz.

FingerTipFun
źródło
0

Włóż to w siebie viewDidLoad, miej nadzieję, że zaowocuje to, czego szukasz

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" 
style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backBarButtonItem;
[backBarButtonItem release];
Ravi_Parmar
źródło
0

jeśli chcesz ustawić tytuł w kontrolerze ARRIVING (czasem więcej logiki ...) w swift 3 zrób:

func setBackButtonNavBar(title: String, delay: Double){

    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in

        if let navBar = self.navigationController?.navigationBar{
            navBar.backItem?.title = title
        }
    })

}

w nadchodzącym kontrolerze:

override func viewDidLoad() {
    super.viewDidLoad()
    self.setBackButtonNavBar(title: "back", delay: 0.3)
}

zwykle umieszczam self.setBackButtonNavBar w rozszerzeniu kontrolera.

ingconti
źródło
0

Wiem, że to stare pytanie, a odpowiedzi są nieco zaktualizowane!

Prostym sposobem jest zrobienie tego w nadrzędnym ViewController:

czyli ten, który przeniesie Cię do następnego kontrolera widoku.

self.navigationItem.backBarButtonItem  = UIBarButtonItem(title: "Custom text here", style: .plain, target: nil, action: nil)
madeny
źródło
-1

Robiąc to w kodzie, usuń styl przycisku Wstecz pliku UINavigationConroller. Jeśli dodasz element nawigacji w każdym ze swoich widoków, możesz ustawić tytuł tylnego przycisku w StoryBoard.

gjseminario
źródło