Registerkartensteuerung in einer Navigationssteuerung oder Freigabe einer Navigationsstammansicht

80

Ich versuche, eine Benutzeroberfläche zu implementieren, die wie in der Tweetie- App strukturiert ist und sich so verhält: Der Ansichts-Controller der obersten Ebene scheint ein Navigations-Controller zu sein, dessen Stammansicht eine Tabellenansicht "Konten" ist. Wenn Sie auf ein Konto klicken, wird die zweite Ebene mit einer Registerkartenleiste im unteren Bereich aufgerufen. Jedes Registerkartenelement zeigt eine andere Liste an und ermöglicht einen weiteren Drilldown (in den folgenden Ebenen wird die Registerkartenleiste nicht angezeigt).

Dies scheint also die Implementierungshierarchie zu sein:

  • UINavigationController
    1. Konten :UITableViewController
    2. UITabBarController
      1. Tweets :UITableViewController
        • Detailansicht eines Tweets / Benutzers / etc.
      2. Antworten :UITableViewController
      3. ...

Dies scheint zu funktionieren [^ 1], scheint jedoch gemäß der SDK-Dokumentation für -pushViewController:animated:(Hervorhebung hinzugefügt) nicht unterstützt zu werden:

viewController : Der View Controller, der auf den Stapel verschoben wird. Es kann keine Instanz von Tab Bar Controller sein.

Ich möchte private APIs und ähnliches vermeiden, bin mir aber nicht sicher, warum diese Verwendung ausdrücklich verboten ist, auch wenn sie anscheinend gut funktioniert. Kennt jemand den Grund?

Ich habe darüber nachgedacht, den Tab-Bar-Controller als Haupt-Controller zu verwenden, wobei jeder der Tabs separate Navigations-Controller enthält. Das Problem dabei ist, dass jeder Navigationscontroller einen einzelnen Root-Ansichtscontroller gemeinsam nutzen muss (nämlich die Tabelle "Accounts" in Tweetie ) - dies scheint nicht zu funktionieren: Wenn Sie den Tabellencontroller auf einen zweiten Navigationscontroller verschieben, wird dieser anscheinend entfernt vom ersten. Ganz zu schweigen von der Buchhaltung bei der Auswahl eines anderen Kontos wäre wahrscheinlich ein Schmerz.

Wie soll ich das richtig umsetzen?

[^ 1]: Der Tab-Bar-Controller muss in Unterklassen unterteilt werden, damit das Navigationselement des Tab-Bar-Controllers auf dieser Ebene mit dem Navigationselement des ausgewählten Tabs synchron bleibt und der Tabellen-Controller des einzelnen Tabs seine jeweiligen Detailansichten self.tabBarController.navigationControlleranstelle von verschieben muss self.navigationController.

Daniel Dickison
quelle

Antworten:

63

Die beiden vorherigen Antworten haben es richtig gemacht - ich verwende es nicht UITabBarControllerin Tweetie. Es ist ziemlich einfach, eine benutzerdefinierte XXTabBarController(einfache Unterklasse von UIViewController) zu schreiben , die gerne auf einen Navi-Controller-Stack übertragen wird, aber dennoch der "View Controller" -Philosophie entspricht. Jede "Registerkarte" in der kontospezifischen Ansicht ( Tweets/ Replies/ Messages) ist eine eigene Ansichtssteuerung, und soweit sie betroffen sind, werden sie von einem einfachen Benutzer auf dem Bildschirm ausgetauscht UITabBarController.

Loren
quelle
2
Wie geht Ihre benutzerdefinierte Controller-Klasse in der Registerkartenleiste mit der Installation der Eigenschaften navigationItem und navigationController der untergeordneten Controller um?
Bvanderveen
Hat sich dies in iOS 5 geändert? Ich scheine in der Lage zu sein, einen UITabBarController ohne allzu große Probleme zu einem UINavigationController hinzuzufügen, selbst als Root-Controller.
sparkFinder
33

Ich erstelle eine App, die ein ähnliches Navigationsframework wie Tweetie verwendet. Ich habe in meinem Blog www.wiredbob.com einen Beitrag darüber geschrieben, der auch auf den Quellcode verweist . Es ist eine vollständige Vorlage, die Sie als Grundlage für ein anderes Projekt verwenden können. Viel Glück!

Robert Conn
quelle
10
Für diejenigen, die sich fragen, ist der Link zu dem erwähnten Blog-Beitrag wiredbob.com/blog/2009/4/20/…
Anh Do
@ Robert Conn, wirklich schönes Tutorial. Ich verwende Ihr Konzept, aber aus irgendeinem Grund ist meine tabBar nicht aktiv. Ist Ihnen dies bei der Implementierung Ihrer App passiert?
Ein Salcedo
@ASalcedo: Auch ich hatte dieses Problem, stellte jedoch fest, dass die Standardhöhengröße von 460 im Quellcode unter www.wiredbob.com zu groß war, da ich die Größe der mit den Elementen der Registerkartenleiste verknüpften Ansichten reduzieren musste Sie werden sehen, dass die Höhe für die Registerkartenelemente 369 beträgt, um die Registerkartenleiste zu berücksichtigen. Um die Höhe im Interface Builder zu ändern, müssen Sie außerdem sicherstellen, dass Status, obere und untere Leiste im Attributinspektor der Ansicht auf "Keine" gesetzt sind (nicht sofort ersichtlich).
Izac
2
Der Blog-Beitrag ist für mich tot. Gibt es eine Chance, dass jemand das herumliegen hat?
Tiago Veloso
10

Es ist möglich, jedem UIViewController eine UITabBar hinzuzufügen. Auf diese Weise müssen Sie keinen UITabBarController pushen und bleiben daher innerhalb der Richtlinien der Apple API.

Im Interface Builder befindet sich UITabBar in der Cocoa Touch Library unter "Windows, Views & Bars".

Himadri Choudhury
quelle
1
Hallo! @Himadri Choudhury können Sie erklären "und daher innerhalb der Richtlinien der Apple API bleiben" - oder die Referenz geben? Ich kann nicht finden, wo diese Richtlinie angegeben ist (ich bezweifle nicht, dass sie existiert, aber ich kann die URL nicht finden). Vielen Dank
Darksider
10

Ich mache das in einigen meiner Apps. Der Trick beim Hinzufügen einer Registerkartenleiste zu einer auf NavigationController basierenden App besteht darin, KEINEN TabBarController zu verwenden. Fügen Sie der Ansicht eine Registerkartenleiste hinzu, machen Sie den Ansichts-Controller für diese Ansicht zu einem TabBarDelegate und reagieren Sie auf Benutzerauswahlen in der Registerkartenleiste im Code des Ansichts-Controllers.

Ich verwende Registerkartenleisten, um der Ansicht der Registerkartenleiste zusätzliche Ansichten als Unteransichten hinzuzufügen, eine Tabellenansicht mit verschiedenen Datensätzen neu zu laden, eine UIPickerView neu zu laden usw.

Alpinista
quelle
6

Ich hatte in der letzten Stunde Probleme, ein zu implementieren, UITabBarda es ausgeblendet werden würde, wenn ich versuchte, meine Ansicht anzuzeigen. dann habe ich diesen Beitrag gefunden :

Stellen Sie grundsätzlich sicher, dass Sie Ihre neue Ansicht unter der Registerkartenleiste gemäß dieser Codezeile einfügen:

[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
Silber
quelle
Vielen Dank, dies hat dazu beigetragen, meine verschwundene Registerkartenleiste zu reparieren. Ich habe den gleichen Code verwendet, den Robert Conn vorgeschlagen hat, aber irgendwie verschwindet die UI-Registerkartenleiste, wenn ich zur zweiten Ansicht wechsle.
Vijay Katam
3

In meiner App ist der Root View Controller ein UINavigation Controller. An einem bestimmten Punkt in der App muss ich eine UITabBar anzeigen. Ich habe versucht, eine UITabBar in einer UIView innerhalb der Navigationshierarchie zu implementieren, wie in einigen der vorherigen Beiträge vorgeschlagen, und dies funktioniert. Ich stellte jedoch fest, dass ich mehr vom Standardverhalten des Registerkarten-Controllers wollte, und fand eine Möglichkeit, den UITabBarController mit dem UINavigation-Controller zu verwenden:

1) Wenn ich die Ansicht des UITabBarControllers anzeigen möchte, gehe ich folgendermaßen vor:

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

2) Wenn ich zu meiner Position in der Navigationshierarchie zurückkehren möchte, gehe ich folgendermaßen vor:

appDelegate.window.rootViewController = myNavControllerInstance;
richardsun
quelle
3

Dies könnte durch einfaches Einbetten des TabBarControllers in den Navigationscontroller erreicht werden. Im Storyboard:

  1. Ziehen Sie einen ViewController
  2. Klicken Sie auf die ViewController-Szene
  3. Klicken Sie auf Editor >> Einbetten in >> Navigation Controller.
  4. Ziehen Sie eine Schaltfläche auf denselben ViewController.
  5. Ziehen Sie einen TabBarController
  6. Verbinden Sie die Schaltfläche am ViewController mit dem TabBarController über Push Segue Action.

In diesem Fall befindet sich nur der RootViewController des TabBarControllers im Stapel des Navigationscontrollers. Alle TabBarItems haben die Navigationsleiste oben und der Benutzer kann jederzeit zum Startbildschirm wechseln, unabhängig vom ausgewählten TabBarItem

Dies kann an jedem ViewController im Stack des Navigationscontrollers erfolgen.

Wenn es funktioniert, schlagen Sie mir bitte vor, wie ich den Ruf verbessern kann, damit ich die Bilder und den Code in der nächsten Antwort veröffentlichen kann. :) :)

caffieneToCode
quelle
3

So habe ich es gemacht. Dies schiebt tatsächlich einen Tabbarcontroller auf den Navigationscontroller. Es funktioniert gut. Ich habe in der Dokumentation nirgends festgestellt, dass Apple diesen Weg nicht unterstützt. Kann mir jemand einen Link zu dieser Warnung geben?

Wenn dies der Fall ist, weigert sich Apple möglicherweise, meine App im Appstore zu veröffentlichen?

-(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
quelle
Sie müssen Ihre UIViewController
Gargo