NavigationStack trong SwiftUI
1. Cơ bản
struct ContentView: View {
var body: some View {
NavigationStack {
List {
NavigationLink("Settings") {
SettingsView()
}
NavigationLink("Profile") {
ProfileView()
}
}
.navigationTitle("Home")
}
}
}2. NavigationLink
Static Destination
NavigationLink("Go to Detail") {
DetailView()
}
NavigationLink {
DetailView()
} label: {
HStack {
Image(systemName: "star")
Text("Favorites")
}
}Value-based (iOS 16+)
struct ProductRow: View {
let product: Product
var body: some View {
NavigationLink(value: product) {
Text(product.name)
}
}
}
struct ContentView: View {
let products: [Product]
var body: some View {
NavigationStack {
List(products) { product in
ProductRow(product: product)
}
.navigationDestination(for: Product.self) { product in
ProductDetailView(product: product)
}
}
}
}3. Navigation Title & Toolbar
NavigationStack {
List { }
.navigationTitle("Products")
.navigationBarTitleDisplayMode(.large) // .inline, .automatic
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Add") { }
}
ToolbarItem(placement: .topBarLeading) {
Button("Edit") { }
}
}
}4. Programmatic Navigation
struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack {
Button("Go to Settings") {
path.append("settings")
}
Button("Go to Profile") {
path.append(User(name: "John"))
}
}
.navigationDestination(for: String.self) { value in
if value == "settings" {
SettingsView()
}
}
.navigationDestination(for: User.self) { user in
ProfileView(user: user)
}
}
}
func navigateToRoot() {
path.removeLast(path.count) // Pop to root
}
}5. Deep Linking
struct AppNavigator: View {
@State private var path: [Route] = []
enum Route: Hashable {
case productList
case productDetail(id: Int)
case cart
case checkout
}
var body: some View {
NavigationStack(path: $path) {
HomeView()
.navigationDestination(for: Route.self) { route in
switch route {
case .productList:
ProductListView()
case .productDetail(let id):
ProductDetailView(id: id)
case .cart:
CartView()
case .checkout:
CheckoutView()
}
}
}
.onOpenURL { url in
// Handle deep link
if url.path.contains("product") {
if let id = Int(url.lastPathComponent) {
path = [.productDetail(id: id)]
}
}
}
}
}6. Custom Back Button
struct DetailView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack {
Text("Detail")
}
.navigationBarBackButtonHidden()
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button {
dismiss()
} label: {
HStack {
Image(systemName: "chevron.left")
Text("Back")
}
}
}
}
}
}7. Search
struct SearchableList: View {
@State private var searchText = ""
let items = ["Apple", "Banana", "Cherry", "Date"]
var filteredItems: [String] {
if searchText.isEmpty {
return items
}
return items.filter { $0.localizedCaseInsensitiveContains(searchText) }
}
var body: some View {
NavigationStack {
List(filteredItems, id: \.self) { item in
NavigationLink(item) {
Text(item)
}
}
.navigationTitle("Fruits")
.searchable(text: $searchText, prompt: "Search fruits")
}
}
}📝 Tóm tắt
| Component | Mục đích |
|---|---|
NavigationStack | Container cho navigation |
NavigationLink | Tạo link điều hướng |
.navigationDestination | Define destinations |
NavigationPath | Programmatic navigation |
Last updated on