Civil & Structural Engineering
Designing a Multi-tab Interface with Swiftui for Better Navigation
Table of Contents
SwiftUI, Apples deklaratives Framework zum Erstellen von Benutzeroberflächen auf allen Apple-Plattformen, bietet eine leistungsstarke und dennoch einfache Möglichkeit, Multi-Tab-Schnittstellen zu erstellen. Tabbed-Navigation ist eines der häufigsten Muster in mobilen und Desktop-Apps, so dass Benutzer schnell zwischen verschiedenen Abschnitten wechseln können, ohne den Kontext zu verlieren. Egal, ob Sie eine inhaltsintensive Nachrichten-App, ein Produktivitäts-Dashboard oder ein Einstellungsfeld erstellen, TabView ist die Go-to-Komponente für die Implementierung von Tab-Navigation.
Dieser Artikel geht durch alles, was Sie über das Entwerfen von Multi-Tab-Schnittstellen mit SwiftUI wissen müssen. Beginnend mit den Grundlagen von TabView werden wir Anpassungen, Zustandsmanagement, erweiterte Muster, Zugänglichkeit, Leistung und reale Beispiele untersuchen. Am Ende werden Sie ausgestattet sein, um produktionsbereite Tabbed-Apps zu erstellen, die die Benutzer begeistern.
Die TabView-Komponente verstehen
Im Mittelpunkt der Tab-Navigation in SwiftUI steht TabView. Es ist eine Containeransicht, die eine Reihe von Kinderansichten darstellt, die jeweils mit einem Tab-Element verknüpft sind. Wenn der Benutzer auf eine Registerkarte tippt, wird die entsprechende Ansicht angezeigt, und die Tableiste zeigt den aktiven Zustand mit einem Highlight an.
Layout und Verhalten
Standardmäßig stellt TabView eine Tab-Leiste am unteren Bildschirmrand unter iOS und oben unter macOS dar. iPadOS passt sich der Geräteausrichtung an und watchOS verwendet einen segmentierten Stil. Sie müssen das Layout der Tab-Leiste nicht selbst verwalten; SwiftUI übernimmt die Positionierung, Dimensionierung und Animation der Tab-Auswahl.
Tab-Elemente mit SF-Symbolen
Apple empfiehlt die Verwendung von SF-Symbolen für Tab-Symbole, da sie perfekt über Geräte und Zugänglichkeitseinstellungen skaliert werden. Der -Modifikator akzeptiert einen View Builder, in dem Sie normalerweise ein mit einem SF-Symbolnamen und einem -Label platzieren.
TabView {
ContentView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
}
Die Label-Ansicht kombiniert automatisch ein Symbol und einen Titel, wodurch eine korrekte Ausrichtung und Zugänglichkeitskennzeichnung gewährleistet wird.
Aufbau eines einfachen Multi-Tab-Interfaces
Erstellen einer einfachen Tabbed-App erfordert nur wenige Zeilen Code. Lassen Sie uns ein minimales Beispiel mit drei Tabs erstellen: Home, Search und Profile.
Schrittweise Umsetzung
- Erstellen Sie eine neue SwiftUI-Ansicht (z. B. ) und fügen Sie eine TabView als Wurzel hinzu.
- Für jede Registerkarte eine Kinderansicht (z. B. eine oder eine benutzerdefinierte Ansicht) angeben.
- Befestigen Sie den -Modifikator mit einem geeigneten SF-Symbol und einer lokalisierten Zeichenfolge.
Codebeispiel
struct ContentView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profile", systemImage: "person.crop.circle")
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Welcome Home")
}
}
struct SearchView: View {
var body: some View {
Text("Find what you need")
}
}
struct ProfileView: View {
var body: some View {
Text("Your profile")
}
}
Dieser Code erzeugt eine Arbeits-Tableiste mit drei Elementen. Jede Registerkarte zeigt bei der Auswahl ihren jeweiligen Inhalt an. SwiftUI verwaltet automatisch die aktiven Zustands- und Übergangsanimationen.
Anpassen von Tab-Elementen
Während das standard-look sauber ist, müssen sie die tab-leiste oft an die marke ihrer app anpassen oder zusätzliches benutzerfeedback geben.
Hinzufügen von Abzeichen und Indikatoren
SwiftUI ermöglicht es Ihnen, ein Badge an jedes Tab-Element mit dem -Modifikator in der Kinderansicht anzubringen. Badges zeigen eine kleine Zahl oder einen kleinen Text an (wie die Anzahl der ungelesenen Benachrichtigungen).
TabView {
InboxView()
.tabItem { Label("Inbox", systemImage: "tray.fill") }
.badge(5) // Shows a red badge with "5"
SettingsView()
.tabItem { Label("Settings", systemImage: "gearshape") }
}
Badges werden automatisch aktualisiert, wenn sie an eine @State oder beobachtete Eigenschaft gebunden sind. Auf iOS erscheint das Badge als roter Kreis mit einer Nummer; auf anderen Plattformen kann es anders dargestellt werden.
Ändern Tab Bar Aussehen (Tintenfarben und Hintergrund)
Um die Akzentfarbe der ausgewählten Registerkarte zu ändern, setzen Sie den -Modifikator auf TabView (alt in neueren iOS-Versionen) oder verwenden Sie den -Modifikator in iOS 15+:
TabView {
// tabs...
}
.tint(.purple)
Für eine erweiterte Anpassung, wie z. B. einen benutzerdefinierten Hintergrund oder eine benutzerdefinierte Form, können Sie bis verwenden oder eine vollständig benutzerdefinierte Tab-Leiste mit einem horizontalen Stapel von Tasten erstellen (siehe Abschnitt benutzerdefinierte Tab-Leiste später).
Verwaltungsstaat und Auswahl
Die Steuerung, welcher Tab aktiv ist, ist für Funktionen wie Deep Linking, Benutzerpräferenzen oder das Zurücksetzen der App auf den ersten Tab nach einer bestimmten Aktion unerlässlich.
Verwenden von @State für die Auswahl
Binden Sie eine Variable @State vom gleichen Typ wie die Tag-Werte an den Parameter TabView Zuweisen einer Ganzzahl (oder eines beliebigen ) Werts mit dem Modifikator.
struct ContentView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tabItem { Label("Home", systemImage: "house.fill") }
.tag(0)
SearchView()
.tabItem { Label("Search", systemImage: "magnifyingglass") }
.tag(1)
ProfileView()
.tabItem { Label("Profile", systemImage: "person.crop.circle") }
.tag(2)
}
}
}
Wenn sich ändert (z.B. über eine Schaltfläche auf dem Startbildschirm), wechselt die Tab-Ansicht automatisch zur entsprechenden Tab. Mit diesem Ansatz können Sie auch die aktuelle Tab an anderer Stelle in Ihrer App lesen.
Programmatic Tab Switching
Sie können Tabs von einer beliebigen Kinderansicht aus ändern, indem Sie eine Bindung an die Auswahlvariable übergeben, z. B. eine Schaltfläche "Zu Einstellungen gehen" auf der Startseite:
struct HomeView: View {
@Binding var selectedTab: Int
var body: some View {
VStack {
Text("Home")
Button("Open Settings") {
selectedTab = 2
}
}
}
}
Integrieren Sie dies, indem Sie die Bindung beim Erstellen der Kinderansicht innerhalb der TabView übergeben.
Persisting Tab Selection mit UserDefaults
Für eine benutzerfreundliche Note, merken Sie sich die letzte ausgewählte Registerkarte nach dem Neustart der App. Verwenden Sie , um die Auswahl automatisch auf UserDefaults fortzusetzen:
struct ContentView: View {
@AppStorage("selectedTab") private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
// tabs...
}
}
}
Die App wird nun auf dem Tab gestartet, den der Benutzer zuletzt besucht hat.
Fortgeschrittene Navigationsmuster
Multi-Tab-Apps müssen oft in Navigationsstacks integriert, eingehende URLs verarbeitet oder Daten zwischen Tabs ausgetauscht werden.
Kombination von TabView mit NavigationView
Jede Registerkarte kann ihre eigene (oder in älterer SwiftUI) enthalten, was es ermöglicht, in Detailansichten innerhalb einer Registerkarte zu bohren, während die Registerleiste sichtbar bleibt.
struct HomeView: View {
var body: some View {
NavigationStack {
List(1..<20) { item in
NavigationLink("Item \(item)", value: item)
}
.navigationDestination(for: Int.self) { item in
DetailView(item: item)
}
.navigationTitle("Home")
}
}
}
Platzieren Sie die innerhalb der Kinderansicht des Tabs, nicht außerhalb der TabView, um separate Navigationsstapel pro Tab zu erhalten.
Umgang mit Deep Links
Wenn Ihre App einen universellen Link oder ein benutzerdefiniertes URL-Schema erhält, müssen Sie möglicherweise zu einer bestimmten Registerkarte wechseln und optional zu einer Unteransicht navigieren. Verwenden Sie den -Modifikator auf TabView (oder die Stammansicht) und analysieren Sie die URL, um den Auswahlzustand zu aktualisieren oder die Triggernavigation auszulösen.
TabView(selection: $selectedTab)
.onOpenURL { url in
// e.g., myapp://tab/2
if let tabNumber = extractTab(from: url) {
selectedTab = tabNumber
}
}
Für komplexere Szenarien kombinieren Sie mit einer Pfadbindung.
Daten zwischen Tabs weitergeben
Da jede Registerkarte eine eigene Ansichtshierarchie hat, erfordert die Datenweiterleitung zwischen ihnen eine gemeinsame Zustandsquelle.
- [FLT:
- StateObject mit einem freigegebenen Manager: Erstellen Sie eine Singleton- oder beobachtbare Klasse und geben Sie sie weiter.
- Mithilfe der Auswahlbindung: Für einfache Werte kann der Auswahlzustand selbst als Kommunikationskanal fungieren (z. B. "Ich bin auf Tab 2 umgestiegen, weil die Daten bereit sind").
Vermeiden Sie übermäßige Komplikationen; halten Sie den Datenfluss nach Möglichkeit unidirektional.
Zugänglichkeit und User Experience
Eine barrierefreie Tab-Oberfläche ist entscheidend, um ein breites Publikum zu erreichen. SwiftUI bietet integrierte Unterstützung für die Barrierefreiheit, aber Sie sollten sie überprüfen und verbessern.
VoiceOver Unterstützung
Tab-Elemente erhalten automatisch Accessibility-Etiketten aus dem Label oder Text, den Sie bereitstellen. Testen Sie, ob jeder Tab seinen Zweck klar vermittelt. Fügen Sie für benutzerdefinierte Tab-Balken und hinzu, um das Systemverhalten nachzuahmen.
Tastaturnavigation
Auf iPadOS mit einer Hardware-Tastatur können Benutzer mit Command-[Nummer] oder Option-Tab zwischen Registerkarten navigieren. SwiftUIs TabView erbt dieses Verhalten automatisch. Stellen Sie sicher, dass Ihre benutzerdefinierte Tab-Implementierung auch Tastaturbefehle unterstützt, indem Sie -Modifikatoren hinzufügen.
Adaptive Layouts
Auf iPhones im Querformat kann die Tabulatorleiste anders aussehen. iOS 15 und höher erlauben es der Tabulatorleiste, sich zu verdichten, wenn der Platz begrenzt ist. Sie können den Tabulatorinhalt mit anpassen, um ein besseres Lese- oder Interaktionserlebnis zu bieten.
Benutzerdefinierte Tab Bars mit SwiftUI
Manchmal braucht man ein Design, das von der System-Tableiste abweicht – z.B. eine schwebende Schaltfläche in der Mitte, eine gebogene Form oder animierte Symbole. Während man einige eingebaute Verhaltensweisen verliert (wie Safe Area Inserts), macht SwiftUI benutzerdefinierte Tab-Bars einfach.
Replizieren von TabView mit Custom Shapes
Erstellen Sie eine benutzerdefinierte Ansicht mit einer von Buttons, die unten überlagert sind.
struct CustomTabView: View {
@State private var selection = 0
var body: some View {
VStack(spacing: 0) {
// Content area
Group {
if selection == 0 {
HomeView()
} else if selection == 1 {
SearchView()
} else {
ProfileView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
// Custom tab bar
HStack {
TabBarButton(icon: "house.fill", label: "Home", isSelected: selection == 0)
.onTapGesture { selection = 0 }
Spacer()
TabBarButton(icon: "magnifyingglass", label: "Search", isSelected: selection == 1)
.onTapGesture { selection = 1 }
Spacer()
TabBarButton(icon: "person.fill", label: "Profile", isSelected: selection == 2)
.onTapGesture { selection = 2 }
}
.padding(.horizontal)
.padding(.top, 8)
.background(Color(uiColor: .systemBackground)
.shadow(radius: 2))
}
.ignoresSafeArea(.keyboard) // Prevent tab bar from moving with keyboard
}
}
Animieren von Tab Transitions
Fügen Sie beim Umschalten der Registerkarten glatte Übergänge hinzu, indem Sie den Inhalt in einen -Block einwickeln. fügen Sie beispielsweise einen Folien- oder Trübungsübergang hinzu. Sie können das Symbol auch mit unter iOS 17+ animieren (wie Bounce oder Puls).
Leistungsoptimierung
Multi-Tab-Apps können unter Speicherblasen leiden, wenn Sie alle Registerkarten eifrig laden. SwiftUIs TabView ist standardmäßig faul: Es erstellt und rendert nur die Ansicht für den ausgewählten Tab. Wenn Sie jedoch zustandsschwere Ansichten verwenden, möchten Sie möglicherweise noch optimieren.
Lazy Loading Tab Inhalt
Verwenden Sie oder innerhalb von Registerkarten, um die Erstellung der Ansicht bis zum Scrollen zu verschieben. Vermeiden Sie die Verwendung komplexer Berechnungen im Initialisierer der Registerkarten-Kinderansichten; verlassen Sie sich stattdessen darauf, dass das Datenladen startet.
Gedächtnislecks vermeiden
Da Tabs häufig Verweise auf Instanzen enthalten, stellen Sie sicher, dass Sie keine unnötigen starken Referenzzyklen erstellen. Verwenden Sie für eigene Objekte und für geteilte. Wenn ein Tab nie angezeigt wird, wird seine Ansicht möglicherweise immer noch im Speicher gehalten - verwenden Sie (einen benutzerdefinierten Wrapper), um die Initialisierung zu verschieben, bis der Tab ausgewählt ist.
Testen Sie Ihr Tabbed Interface
Automatisierte Tests tragen dazu bei, dass die Tab-Navigation korrekt über Gerätezustände hinweg funktioniert.
Unit Tests für Tab Selection
Da Ihre Tab-Ansicht von einer Variablen gesteuert wird, können Sie die Logik testen, die sich ändert Zum Beispiel, validieren Sie, dass ein Deep Link den Tab-Index korrekt analysiert und zuweist.
func testTabSelectionViaDeepLink() {
let url = URL(string: "myapp://tab/2")!
let tabNumber = extractTab(from: url)
XCTAssertEqual(tabNumber, 2)
}
UI-Tests mit XCTest
Verwenden Sie XCUITest, um zu überprüfen, ob das Tippen auf ein Tab-Element den richtigen Inhalt anzeigt.
func testTappingSearchTab() {
let app = XCUIApplication()
app.launch()
let searchTab = app.tabBars.buttons["Search"]
XCTAssertTrue(searchTab.exists)
searchTab.tap()
XCTAssertTrue(app.staticTexts["Find what you need"].exists)
}
Real-World-Beispiel: Ein Multi-Tab-Dashboard
Lassen Sie uns alles mit einem praktischen Beispiel zusammenbringen: eine Dashboard-App mit drei Tabs - Übersicht, Analysen und Einstellungen.
Übersicht Tab
Zeigt eine Zusammenfassung der wichtigsten Kennzahlen (wie tägliche aktive Benutzer, Einnahmen) in einem scrollbaren an. Verwendet , um detaillierte Berichte zu bohren.
Analytics Tab
Enthält Diagramme und Graphen, die mit Swift Charts erstellt wurden. Da das Diagramm-Rendering schwer sein kann, markieren Sie die Ansicht als und lösen Sie das Laden von Daten nur aus, wenn der Tab angezeigt wird.
Tab Einstellungen
Zeigt eine Liste von Umschaltern, Links und einer Anmeldetaste an. Diese Registerkarte muss möglicherweise auf ein Umgebungsobjekt zugreifen, das die Benutzersitzung enthält. Wenn Sie dies über weitergeben, wird sichergestellt, dass alle Registerkarten die gleichen Daten teilen.
Häufige Fallstricke und Lösungen
Selbst erfahrene SwiftUI-Entwickler stoßen auf einige wiederkehrende Probleme mit TabView.
Tab Bar verschwindet im Navigationsstapel
Wenn Sie eine Ansicht auf einen Navigationsstapel innerhalb einer Registerkarte drücken, kann die Registerleiste beim Drücken verschwinden. Lösung: Verwenden Sie (iOS 16+) anstelle von – die Registerleiste bleibt sichtbar.
Falsche Tag-Werte
Wenn Sie nicht jedem Kind zuweisen, wird die Auswahlbindung möglicherweise nicht korrekt in der Registerkarte berücksichtigt.
Tab Ansicht Rücksetzzustand
Manchmal wird beim Wechseln der Registerkarten der Status der Kindansicht zurückgesetzt. Dies ist von Grund auf – SwiftUI erstellt jedes Mal, wenn sie angezeigt werden muss, eine neue Instanz der Kinderansicht. Um den Zustand über Registerkartenschaltern zu erhalten, heben Sie den Zustand in eine übergeordnete Ansicht oder verwenden Sie auf einer Ebene über TabView.
Schlussfolgerung
Die TabView-Komponente bietet Ihnen eine solide Grundlage, und mit ein paar zusätzlichen Codezeilen können Sie Badges hinzufügen, den Status verwalten, Navigationsstacks integrieren und sogar vollständig benutzerdefinierte Tab-Bars erstellen. Durch die Einhaltung von Best Practices für Zugänglichkeit, Leistung und Testen erstellen Sie ein ausgefeiltes Navigationserlebnis, das sich über alle Apple-Plattformen hinweg skalieren lässt.
Weiter erkunden, indem Sie in die offizielle TabView-Dokumentation von Apple eintauchen, die Richtlinien für menschliche Benutzeroberflächen für Tableisten lernen und mit den Symbolen von FLT: 5 experimentieren, um Ihren Tabs ein ausgefeiltes, systemkonsistentes Aussehen zu verleihen.