Kontroler paska kart w kontrolerze nawigacji lub udostępnianie widoku głównego nawigacji

80

Próbuję zaimplementować interfejs użytkownika o strukturze podobnej do aplikacji Tweetie , która zachowuje się tak: kontroler widoku najwyższego poziomu wydaje się być kontrolerem nawigacji, którego głównym widokiem jest widok tabeli „Konta”. Kliknięcie dowolnego konta powoduje przejście do drugiego poziomu, na którym u dołu znajduje się pasek kart. Każdy element karty przedstawia inną listę i pozwala na dalsze drążenie w dół (kolejne poziomy nie pokazują paska kart).

Wygląda więc na to, że hierarchia implementacji jest następująca:

  • UINavigationController
    1. Konta :UITableViewController
    2. UITabBarController
      1. Tweety :UITableViewController
        • Szczegółowy widok tweeta / użytkownika / itp
      2. Odpowiedzi :UITableViewController
      3. ...

Wydaje się, że to działa [^ 1], ale wydaje się, że nie jest obsługiwane zgodnie z dokumentacją SDK dla -pushViewController:animated:(podkreślenie dodane):

viewController : kontroler widoku, który jest wypychany na stos. Nie może być instancją kontrolera paska kart.

Chciałbym unikać prywatnych interfejsów API i tym podobnych, ale nie jestem pewien, dlaczego takie użycie jest wyraźnie zabronione, nawet jeśli wydaje się działać dobrze. Czy ktoś zna powód?

Myślałem o umieszczeniu kontrolera paska zakładek jako głównego kontrolera, z każdą zakładką zawierającą oddzielne kontrolery nawigacji. Problem polega na tym, że każdy kontroler nawigacyjny musi współdzielić jeden główny kontroler widoku (mianowicie tabelę „Konta” w Tweetie ) - to nie działa: przeniesienie kontrolera tabeli do drugiego kontrolera nawigacyjnego wydaje się go usuwać od pierwszego. Nie wspominając o całej księgowości przy wyborze innego konta prawdopodobnie byłoby uciążliwe.

Jak mam to zaimplementować we właściwy sposób?

[^ 1]: Kontroler paska kart musi mieć podklasę, aby element nawigacyjny kontrolera paska kart na tym poziomie pozostawał zsynchronizowany z elementem nawigacyjnym wybranej karty, a kontroler tabeli pojedynczej karty musi przesyłać odpowiednie widoki szczegółów do self.tabBarController.navigationControllerzamiast self.navigationController.

Daniel Dickison
źródło

Odpowiedzi:

63

Dwie poprzednie odpowiedzi są poprawne - nie używam UITabBarControllerw Tweetie. Bardzo łatwo jest napisać niestandardową XXTabBarController(zwykłą podklasę UIViewController), która z przyjemnością zostanie wypchnięta na stos kontrolera nawigacyjnego, ale nadal będzie funkcjonować zgodnie z filozofią „kontrolera widoku”. Każda „karta” w widoku specyficznym dla konta ( Tweets/ Replies/ Messages) jest własnym kontrolerem widoku i jeśli o to chodzi, są zamieniane na ekranie przez zwykły ol UITabBarController.

Loren
źródło
2
W jaki sposób Twoja niestandardowa klasa kontrolera paska kart obsługuje instalację wodną dla właściwości navigationItem i navigationController kontrolerów podrzędnych?
bvanderveen
Czy zmieniło się to w iOS 5? Wydaje mi się, że jestem w stanie dodać UITabBarController do UINavigationController bez większego problemu, nawet jako główny kontroler.
sparkFinder
33

Tworzę aplikację, która używa podobnej struktury nawigacji do Tweetie. Napisałem post o tym, jak to zrobić na moim blogu www.wiredbob.com, który również zawiera linki do kodu źródłowego. To pełny szablon, który możesz wykorzystać jako podstawę do innego projektu. Powodzenia!

Robert Conn
źródło
10
Dla tych, którzy się zastanawiają, link do wspomnianego posta na blogu to wiredbob.com/blog/2009/4/20/…
Anh
@Robert Conn, naprawdę fajny tutorial. Używam twojej koncepcji, ale z jakiegoś powodu mój pasek tabBar nie jest aktywny. Czy to ci się przydarzyło podczas wdrażania aplikacji?
Salcedo
@ASalcedo: Ja też miałem ten problem, ale stwierdziłem, że to dlatego, że musiałem zmniejszyć rozmiar widoków powiązanych z elementami paska zakładek, domyślny rozmiar wysokości 460 był zbyt duży, w kodzie źródłowym na www.wiredbob.com zobaczysz, że wysokość ustawiona dla elementów kart wynosi 369, aby uwzględnić pasek kart. Aby zmienić wysokość w konstruktorze interfejsu, musisz również upewnić się, że status, górny i dolny pasek są ustawione na brak w inspektorze atrybutów widoku (nie jest to od razu oczywiste).
Izac
2
Ten wpis na blogu jest dla mnie martwy, czy jest jakaś szansa, że ​​ktoś to leży?
Tiago Veloso
działający link do posta na blogu: wiredbob.com/2009/04/iphone-tweetie-style-navigation.html
oluckyman
10

Możliwe jest dodanie UITabBar do dowolnego UIViewController. W ten sposób nie musisz w rzeczywistości naciskać UITabBarController, a zatem przestrzegać wytycznych Apple API.

W kreatorze interfejsów UITabBar znajduje się w sekcji „Okna, widoki i bary” w bibliotece Cocoa Touch Library.

Himadri Choudhury
źródło
1
Cześć! @Himadri Choudhury Czy możesz wyjaśnić, „a zatem trzymać się wytycznych Apple API” - lub podać odniesienie? Nie mogę znaleźć miejsca, w którym podano tę wskazówkę (nie wątpię, że istnieje, ale nie mogę znaleźć adresu URL). Dziękuję bardzo
darksider
10

Robię to w kilku moich aplikacjach. Sztuczka polegająca na dodaniu paska kart do aplikacji opartej na navigationController polega na tym, aby NIE używać TabBarController. Dodaj pasek kart do widoku, ustaw kontroler widoku dla tego widoku jako TabBarDelegate i odpowiadaj na wybory użytkownika na pasku kart w kodzie kontrolera widoku.

Używam pasków zakładek, aby dodać dodatkowe widoki do widoku paska zakładek jako podwidoki, aby ponownie załadować widok tabeli z różnymi zestawami danych, aby ponownie załadować UIPickerView itp.

Alpinista
źródło
6

Przez ostatnią godzinę walczyłem z zaimplementowaniem a, UITabBarponieważ ukrywał się, gdy próbowałem wyświetlić mój widok; wtedy znalazłem ten post :

Zasadniczo upewnij się, że wstawiłeś nowy widok poniżej paska kart, zgodnie z tym wierszem kodu:

[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
esilver
źródło
Dzięki temu pomogło to naprawić mój znikający pasek kart. Użyłem tego samego kodu, który zaproponował Robert Conn, ale w jakiś sposób pasek karty interfejsu użytkownika znika, gdy przełączam się do drugiego widoku.
Vijay Katam
3

W mojej aplikacji główny kontroler widoku jest kontrolerem UINavigation. W pewnym momencie aplikacji muszę wyświetlić UITabBar. Próbowałem zaimplementować UITabBar na UIView w hierarchii nawigacji, jak sugerowały niektóre z poprzednich postów, i to działa. Ale stwierdziłem, że chcę więcej domyślnego zachowania, które zapewnia kontroler kart, i znalazłem sposób na użycie UITabBarController z kontrolerem UINavigation:

1) Kiedy chcę wyświetlić widok UITabBarControllera, robię to:

MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;

2) Kiedy chcę wrócić do miejsca, w którym byłem w hierarchii nawigacji, robię to:

appDelegate.window.rootViewController = myNavControllerInstance;
richardsun
źródło
3

Można to osiągnąć, po prostu osadzając TabBarController w kontrolerze nawigacji. W scenorysie:

  1. Przeciągnij ViewController
  2. Kliknij scenę ViewControllera
  3. Kliknij edytor >> Umieść w >> Kontroler nawigacji.
  4. Przeciągnij przycisk na tym samym ViewController.
  5. Przeciągnij TabBarController
  6. Połącz przycisk na ViewController z TabBarController poprzez push Segue Action.

W takim przypadku na stosie kontrolera nawigacji będzie tylko RootViewController TabBarControllera. Wszystkie TabBarItems miałyby pasek nawigacji u góry, a użytkownik może przejść do ekranu głównego w dowolnym momencie, niezależnie od wybranego TabBarItem

Można to zrobić w dowolnym kontrolerze ViewController w stosie kontrolera nawigacji.

Jeśli to zadziała, zasugeruj mi, jak zwiększyć reputację, abym mógł zamieścić zdjęcia i kod w następnej odpowiedzi. :)

caffieneToCode
źródło
3

Tak to zrobiłem. W rzeczywistości jest to umieszczenie kontrolera tabulacji na kontrolerze nawigacyjnym. To działa dobrze. Nigdzie w dokumentacji nie znalazłem, by Apple nie obsługiwał w ten sposób. Czy ktoś może mi podać link do tego ostrzeżenia?

Jeśli to prawda, czy możliwe jest, że Apple odmówi opublikowania mojej aplikacji w Appstore?

-(void)setArrayAndPushNextController
{
    MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
    MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];

    myFirstViewController.array = self.array;


    NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
    UITabBarController *tab = [[UITabBarController alloc] init];
    tab.viewControllers = array;

    [array release];

    UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:@"first title" image:nil tag:1];
    UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:@"second title" image:nil tag:2];

    myFirstViewController.tabBarItem = item1;
    mySecondViewController.tabBarItem = item2;

    [self stopAnimatingSpinner];

    [self.navigationController pushViewController:tab animated:YES];

    [tab release];
    [item1 release];
    [item2 release];
}
savudin
źródło
nie możesz wydać swoich UIViewControllers
Gargo